五一结束了,假期总是过得那么快,不知道前两篇的内容大家记住多少了呢?五一后找工作的小伙伴们评论区举爪组队咯~
原生JS篇
JS是一种什么样的语言?
解释性脚本语言,代码不进行预编译
主要用来向HTML页面添加交互行为
可以直接嵌入HTML页面,但单独写成JS文件有利于结构和行为的分离
跨平台性,在绝大多数浏览器的支持下,可以在多种平台下运行:linux、windows
JS数据类型有哪些?
栈: (原始数据) string/number/boolean/null/undefined/symbol
堆: (引用数据类型)object(array和函数属于object)
数据类型一共7(6种基本类型+1种引用类型)种
object是Javascript中所有对象的父对象
数据封装类对象:Object、Array、Boolean、Number和String
其他对象:Function、Arguments、Math、Date、RegExp、Error
栈与堆的储存位置不同;
原始数据是储存在栈中简单数据段,体积小,大小固定,属于频繁使用的数据.
引用数据类型是储存在堆中的对象,占据的空间大,如果储存在栈中会影响运行性能,引用数据类型在栈中指明了自己的所在地。当代码解析时,会先从栈中获取地址,然后再从堆中获取实体;
**作用域:**每一个变量、函数都有其作用的范围,超出范围不得使用,这个叫做作用域
全局变量、局部变量:
全局变量:在全局范围内声明的变量,如var a =1;
只有赋值没有声明的值,如a =1(注:如果a=2在函数环境中,也是全局变量)
局部变量:写入函数的变量,叫做局部变量,作用范围仅限函数内部
作用:程序安全,内存的释放
作用域链:
查找变量的过程。先找自己局部环境内部有没有声明或者是函数,如果有,则查看声明有无赋值或者是函数的内容,如果没有,则向上一级查找。
变量声明提升:
在预编译阶段,编译器会把所有定义的变量全部提升到最顶部,即,把变量声明的语句会自动放置在最顶部。
当函数内部没有a这个变量的时候,才会向上一级查找
如何转化类型?转数组parseFloat();
转字符串toString()/string()
数组转字符串 join();
字符串转数组: split();
面向过程就是分析出解决问题所需要的步骤,然后用函数吧这些步骤一步一步实现,使用的时候一个一个一次调用就可以了
面向对象是把构成问题事务分解成各个对象,建立对象的目的不是为了完成一个步骤,而是为了描述某个实物在整个解决问题的步骤中的行为面向对象是以功能来划分问题,而不是步骤面向对象编程思想基本思想是使用对象、类、继承、封装等基本概念来进行程序设计
优点:易维护
Js中的this,一般取决于调用这个函数的方法
1、如果函数被实例化(new 构造函数名())的情况下,this指向全新的对象
2、如果是某标签触发什么事件,调用了这个函数,this指向标签(整个DOM节点,包含它的子元素);
3、如果函数使用了call/apply,this是作为参数传入对象
4、有时候this指向不明确的话,this会指向window,ES6中的箭头函数修改了this指向,永远指向作用域
js中this的用法(经典):
this是js的关键字,随着函数使用场合不同,this的值会发生变化。但是总有一个原则,那就是this指的是调用函数的那个对象。
//纯粹的函数调用,this指向全局
function test(){
// this.x = 1;
console.log(this);
}
test();
//作为方法调用,那么this就是指向这个上级对象
function test1(){
console.log(this)
}
var obj = {}
obj.x = test1;
obj.x()
//构造函数调用,就是生成一个新的对象,这里的this指向这个对象
function test2(){
console.log(this)
}
var m = new test2();
//apply调用
//this指向的事apply中的第一个参数
var x = 0;
function test3(){
console.log(this.x);
}
var o = {};
o.x = 1;
o.m =test3;
o.m.apply(); //0
o.m.apply(o); //1
☆说说JS原型和原型链
原型:函数都要prototype(显示原型)属性,而prototype会自动初始化一个空对象,这个对象就是原型对象
原型对象中会有一个constructor属性,这个属性将指向了函数本身
实例化对象都有一个_proto_(隐式原型)属性,_proto_属性指向原型对象
原型链:从实例对象往上找构造这个实例的相关对象,然后这个关联的对象再往上找,找到创造它的上一级的原型对象,以此类推,一直到object.prototype原型对象终止,原型链结束.
原型链中的原型对象中的内容,是会被不同的实例,所共有的
instanceof用于判断引用类型属于哪个构造函数的方法
var arr = [];
arr instanceof Array; //true
typeof arr; //object typeof是无法判断是否为数组的
原理:
instanceof是用来判断实例的_proto_和构造函数的prototype是否指向一个原型对象,
但是有一个弊端,只要出现在一条原型链上的,都会返回true(每个函数都有prototype,每个对象都有一个内部属性__proto__,其指向它的原型对象。原型对象也是一个对象,所以也有__proto__)
这个时候要用实例__proto__.constructor更加严谨
var arr = [ ];
console.log(arr instanseof Array); //true
console.log(arr.__proto__.constructor === Array) //true
☆call和apply的区别和作用?
apply和call都是调用一个对象的一个方法,用另一个对象替换当前对象。
相同点:方法的含义是一样的,即方法功能是一样的。并且第一个参数的作用是一样的
不同点:call可以传入多个参数、apply只能传入两个参数,所以其第二个参数往往是作为数组形式传入
存在意义:实现(多重)继承
原型链继承、构造继承、实例继承、拷贝继承、组合继承、寄生组合继承
继承详情解释:
既然要实现继承,那么我们首先要有一个父类,代码如下:
//先定义一个父类
function Animal(name){
//属性
this.name = name || 'Animal';
//实例方法
this.sleep = function(){
console.log(this.name + "正在睡觉!")
}
}
//原型方法
Animal.prototype.eat = function(food){
console.log(this.name + "正在吃" + food);
}
原型链继承
核心:将父类的实例作为子类的原型
//原型链继承
function Cat(){ }
Cat.prototype = new Animal();
Cat.prototype.name = "cat";
//Test Code
var cat = new Cat();
console.log(cat.name); //cat
console.log(cat.eat("fish")); //cat正在吃fish
console.log(cat.sleep()); //cat正在睡觉
console.log(cat instanceof Animal); //true
console.log(cat instanceof Cat); //true
特点:
1、非常纯粹的继承关系,实例是子类的实例,也是父类的实例
2、父类新增原型方法、原型属性,子类都能够访问到
3、简单,易于实现
缺点:
//构造函数
function Cat(name){
Animal.call(this);
this.name = name || "Tom"
}
//Test Code
var cat = new Cat();
console.log(cat.name); //Tom
console.log(cat.sleep()); //Tom正在睡觉
console.log(cat instanceof Animal); //false
console.log(cat instanceof Cat); //true
特点:
解决了1中,子类实例共享父类引用属性的问题 创建子类实例时,可以向父类传递参数 可以实现多继承(call多个父类对象)//实例继承
function Cat(name){
var instance = new Animal();
instance.name = name || "Tom";
return instance;
}
//Test Code
var cat = new Cat();
console.log(cat.name); //Tom
console.log(cat.sleep()); //Tom正在睡觉!
console.log(cat instanceof Animal); //true
console.log(cat instanceof Cat); //false
特点:
不限制调用方法,不管是new子类()还是子类(),返回的对象具有相同的效果//拷贝继承
function Cat(name){
var animal = new Animal();
for(var p in animal){
Cat.prototype[p] = animal[p];
}
Cat.prototype.name = name || "Tom"
}
//Test Code
var cat = new Cat();
console.log(cat.name); //Tom
console.log(cat.sleep()); //Tom正在睡觉!
console.log(cat instanceof Animal); //false
console.log(cat instanceof Cat); //true
特点:
支持多继承//组合继承
function Cat(name){
Animal.call(this);
this.name = name || "Tom";
}
Cat.prototype = new Animal();
//组合继承也需要修复构造函数的指向问题
Cat.prototype.constructor = Cat;
//Test Code
var cat = new Cat();
console.log(cat.name); //Tom
console.log(cat.sleep()); //Tom正在睡觉!
console.log(cat instanceof Animal); //true
console.log(cat instanceof Cat); //true
特点:
弥补了方法2的缺陷,可以继承实例属性、方法,也可以继承原型属性和方法 既是子类的实例,也是父类的实例 不存在引用属性共享的问题 可传参 函数可复用//寄生组合继承
function Cat(name){
Animal.call(this);
this.name = name || "Tom"
}
(function(){
//创建一个没有实例方法的类
var Super = function(){};
Super.prototype = Animal.prototype;
//将实例作为子类的原型
Cat.prototype = new Super();
})();
//Test Code
var cat = new Cat();
console.log(cat.name); //Tom
console.log(cat.sleep()); //Tom正在睡觉!
console.log(cat instanceof Animal); //true
console.log(cat instanceof Cat); //true
//该实现没有修复constructoe
特点:
堪称完美由于在js中,变量到的作用域属于函数作用域,在函数执行后作用域会被清除、内存也会随之被回收,但是由于闭包是建立在一个函数内部的子函数,由于其可访问上级作用域的原因,即使上级函数执行完,作用域也不会随之销毁,这时的子函数—也就是闭包,便拥有了访问上级作用域中的变量权限,即使上级函数执行完后,作用域内的值也不会被销毁。
闭包解决了什么:在本质上,闭包就是将函数内部和函数外部连接起来的一座桥梁。
由于闭包可以缓存上级作用域,那么就使得函数外部打破了“函数作用域”的束缚,可以访问函数内部的变量。以平时使用的Ajax成功回调为例,这里其实就是个闭包,由于上述的特性,回调就拥有了整个上级作用域的访问和操作能力,提高了几大的便利。开发者不用去写钩子函数来操作审计函数作用域内部的变量了。
闭包有哪些应用场景:
闭包随处可见,一个Ajax请求的成功回调,一个事件绑定的回调函数,一个setTimeout的延时回调,或者一个函数内部返回另一个匿名函数,这些都是闭包。简而言之,无论使用何种方式对函数类型的值进行传递,当函数在别处被调用时都有闭包的身影
闭包的缺陷:由于闭包打破了函数作用域的束缚,导致里面的数据无法清除销毁,当数据过大时会导致数据溢出
事件代理(事件委托):
事件代理是将子元素的事件写一个父元素,让父元素代替处理,内部使用e.target,e.target就是触发这个事件的子元素事件的各个阶段
捕获阶段 —> 目标阶段 —> 冒泡阶段
document —> target目标 —> document
由此addEventListener的第三个参数设置为true和false的区别已经非常清晰了
true—>代表该元素在事件的”捕获阶段”(由外向内传递)响应事件
false —>表示该元素在事件的”冒泡阶段”(由内向外传递)响应事件
new创建了一个对象,共经历了4个阶段:
1、 创建一个空对象
2、 设置原型链
3、让实例化对象中的this指向对象,并执行函数体
4、 判断实例化对象的返回值类型
回调函数
优点:简单、容易理解
缺点:不利于维护,代码耦合高
-事件监听(采用时间驱动模式,取决于某个事件是否发生)
优点:容易理解,可以绑定多个事件,每个时间可以指定多个回调函数
缺点:事件驱动型,流程不够清晰
-发布、订阅(观察者模式)
类似于事件监听,但是可以通过‘消息中心’,了解现在有多少发布者,多少订阅者
Promise对象
优点:可以利用then方法,进行链式写法;可以书写错误时的回调函数;
缺点:编写和理解,相对比较难
Generator函数
优点:函数体内外的数据交换、错误处理机制
缺点:流程管理不方便
async函数
优点:内置执行器、更好的语义、更广的适用性、返回的是Promise,结构清晰
缺点:错误处理机制
数据类型、运算、对象、Function、继承、闭包、作用域、原型链、事件、RegExp、JSON、Ajax、DOM、BOM、内存泄漏、跨域、异步装载、模板引擎、前端MVC、MVVM、路由、模块化、Canvas、ECMAScript
js延迟加载的方法有哪些?defer和async、动态创建DOM方式(用的最多),按需异步载入JS
defer属性:(页面load后执行)
script标签定义了defer属性
用途:表明脚本在执行时不会影响页面的构造。也就是所,脚本会被延迟到整个页面解析完毕之后再执行。
async属性:(页面load前执行)
script标签定义了async属性。与defer属性类似,都用于改变处理脚本的行为。同样,只适用于外部脚本文件。
目的:不让页面等待脚本下载和执行,从而异步加载页面其他内容。异步脚本一定会在页面load事件前执行。不能保证脚本会按顺序执行
1、document.write(); 不常用,因为容易覆盖原来的页面。
2、innerHTML = (); 用的比较多。绑定属性和内容比较方便。(节点套节点)
3、document.createElement(); 用得也比较多,指定数量的时候一般用它。
数组从小到大排序?方法一: sort方法
var array = [1, 4, -8, -3, 6, 12, 9, 8];
function compare(val1, val2) {
return val1 - val2;
};
array.sort(compare);
document.write(array);
方法二:冒泡排序
var array = [1, 4, -8, -3, 12, 9];
function sort(arr) {
for(var i = 0;i < arr.length;i++){
////两两比较,如果前一个比后一个大,则交换位置
for(var j = i + 1; j arr[j]) {
var temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
}
}
sort(array);
console.log(array)
查看其他排序方式可以看:
https://www.cnblogs.com/real-me/p/7103375.html
求从大到小排序可以先使数组从大到小排序,然后添加reverse()方法,使数组顺序颠倒
方法一:trim()方法------仅能取掉字符串首尾空格
var str = " a b c "
console.log(“trim”,str.trim());
//trim原理
function Trim(str){
return str.replace(/(^\s*)|(\s*$)/g, “”);
}
方法二:去除字符中所有的空格
str.replace(/\s/ig,'')
如何实现数组的随机排序?
最快是给数组添加原生sort()方法,可以随机数组,如果sort(),方法没有参数的话,就是依照数据的unicode ['junɪˌkod]码排序的
可以在sort()中添加一个比较函数函数:
function(a,b){ return Math.rendom()>.5? -1:1 }
Math.rendom()在0到1之间生成一个随机数
图片懒加载图片懒加载理解:由于商城图片过多时,就会给图片加一个懒加载的缓冲效果。当图片进入可视化区域的时候才会加载,否则图片只是一个空标签。这样可以优化页面渲染速度,提升用户体验。
思路:将页面中的所有img属性src用data-src代替,当页面滚动至此图片出现在可视区域时,用js取到该图片的data-src值赋给src。
所用知识点:
浏览器可视区域的宽高:
js : document.body.clientWidth/clientHeight
jquery: var windHeight = (window).width()/(window).width()/(window).width()/(window).height();
获取滚动条相对于顶部的高度:
js : document.body.scrollTop;
jquery : var scrollTop=(window).scrollTop;获得元素对于浏览器顶部的高度:js:DOM元素.offsetTop;jquery:varimgTop=(window).scrollTop;
获得元素对于浏览器顶部的高度:
js : DOM元素.offsetTop;
jquery: var imgTop=(window).scrollTop;获得元素对于浏览器顶部的高度:js:DOM元素.offsetTop;jquery:varimgTop=(‘img’).offset().top
判断元素是否出现在浏览器的可视化区域内:
元素相对于顶部的高度 - 浏览器可视化区域的高度 < 小于滚动条到顶部的高度
成立就代表出现 : 不成立就没出现
怎样排除首屏的图片
元素到顶部距离 - 浏览器的可视化高度 > 0
排除已加载的图片
$(this).attr(‘src’) != $(this).attr(‘data-src’) //排除已加载的图片
Jquery实现图片懒加载 :
// 注意: 需要引入jQuery和underscore
$(function() {
// 获取window的引用:
var $window = $(window);
// 获取包含data-src属性的img,并以jQuery对象存入数组:
var lazyImgs = _.map($('img[data-src]').get(), function (i) {
return $(i);
});
// 定义事件函数:
var onScroll = function() {
// 获取页面滚动的高度:
var wtop = $window.scrollTop();
// 判断是否还有未加载的img:
if (lazyImgs.length > 0) {
// 获取可视区域高度:
var wheight = $window.height();
// 存放待删除的索引:
var loadedIndex = [];
// 循环处理数组的每个img元素:
_.each(lazyImgs, function ($i, index) {
// 判断是否在可视范围内:
if ($i.offset().top - wtop < wheight) {
// 设置src属性:
$i.attr('src', $i.attr('data-src'));
// 添加到待删除数组:
loadedIndex.unshift(index);
}
});
// 删除已处理的对象:
_.each(loadedIndex, function (index) {
lazyImgs.splice(index, 1);
});
}
};
// 绑定事件:
$window.scroll(onScroll);
// 手动触发一次:
onScroll();
onScroll()函数最后要手动触发一次,因为页面显示时,并未触发scroll事件。如果图片已经在可视化区域内,这些图片仍然是loading状态,需要手动触发一次,就可以正常显示。
js中常见的内存泄漏 内存泄漏会导致一系列问题,比如:运行缓慢、崩溃、高延迟 内存泄漏是指你用不到(访问不到)的变量,依然占据着内存空间,不能被再次利用起来 意外的全局变量,这些都是不会被回收的变量(除非设置null或者被重新赋值),特别是那些用来临时存储大量信息的变量 周期函数一直在运行,处理函数并不会被回收,jq在移除节点前都会,将事件监听移除 js代码中有对DOM节点的引用,dom节点被移除的时候,引用还维持 深拷贝和浅拷贝的问题: 深拷贝和浅拷贝值针对Object和Array这样的复杂类型 a和b指向了同一块内存,所以修改其中任意一个值,另外一个值也会随之变化,这是浅拷贝 a和b指向同一块内存,但是修改其中任意一个值,另外一个调用的变量,不会受到影响,这是深拷贝 浅拷贝:“Object.assign()”方法用于将所有可枚举的属性的值从一个或多个源对象复制到目标对象,它将返回目标对象 深拷贝:JSON.parse( )和JSON.stringify( )给了我们一个基本的解决办法。但是函数不能被正确处理 显示转换与隐式转换JS中有5中简单的数据类型(也称之为基本数据类型):undefined、Null、Boolean、Number、String。还有一种复杂的数据--------Object,Object本质是一组无序的名值对组成的。
对一个值使用typeof操作符可以返回该值的数据类型,typeof操作符会返回一些令人迷惑但技术上却正确的值,比如调用typeof null会返回“object”,应为特殊值null被认为是一个空的对象引用。
**显式转换:**主要通过JS定义的数据转换方法
各种数据类型及其对应的转化规则:
数据类型 转换为true的值 转换为false的值
Boolean true false
String 任何非空字符串 “” (空字符串)
Number 任何非零数字值(包括无穷大) 0和NaN
Object 任何对象 null
Underfined n/a undefined
**隐式转换:**是系统默认的,不需要加以声明就可以进行的转换。一般情况下,数据的类型转换通常是由编译系统自动进行的,不需要人工干预
大致规则如下:
1、 对象和布尔值比较
对象和布尔值比较时,对象先转换为字符串,然后再转换为数字,布尔值直接转换为数字
2、对象和字符串比较
对象和字符串进行比较时,对象转换为字符串,然后两者进行比较
3、对象和数字比较
对象和数字进行比较时,字符串转换为数字,二者再比较
4、字符串和数字比较
字符串和数字进行比较时,字符串转换成数字,二者再比较,true=1,false=0
5、字符串和布尔值比较
字符串和布尔值进行比较时,二者全部转换成数值再比较
6、布尔值和数字比较
布尔值和数字进行比较时,布尔转换为数字,二者比较
点击父元素只会触发父元素事件,不会影响到子元素,如果点击子元素,会因为冒泡触发父元素的点击事件,可是阻止默认冒泡事件;
mouseover/mouseout与mouseenter/mouseleave的区别与联系1、mouseover/mouseout是标准事件,所有浏览器都支持;mouseenter/mouseleave是IE5.5引入的特有事件,后来被DOM3标准采纳,现代浏览器也支持
2、mouseover/mouseout是冒泡事件;mouseenter/mouseleave不冒泡.需要为多个元素监听鼠标移入/移出事件时,推荐使用mouseover、mouseout托管,提高性能
这两个API都可以遍历数组
forEach函数,是给数组中的每个都执行一遍回调函数,不会返回一个值
Map方法是通过调用数组中的每个元素,映射到新元素中,从而床架一个新数组
如果是复合型类型时,如果只改变复合类型的其中某个value时,将可以正常使用
JS判断设备来源
function deviceType(){
var ua = navigator.userAgent;
var agent = ["Android", "iPhone", "SymbianOS", "Windows Phone", "iPad", "iPod"];
for(var i=0; i0){
break;
}
}
}
deviceType();
window.addEventListener('resize', function(){
deviceType();
})
微信的 有些不太一样
function isWeixin(){
var ua = navigator.userAgent.toLowerCase();
if(ua.match(/MicroMessenger/i)=='micromessenger'){
return true;
}else{
return false;
}
}
DOM元素的e的e.getAttribute(propName)和e.propName有什么区别和联系?
e.getAttribute()是标准DOM操作文档元素属性的方法,具有通用性可在任意文档上使用,返回元素在源文件中设置的属性
e.propName通常是在HTML文档中访问特定元素的特性,浏览器解析元素后生产对应对象,这些对象的特性会根据特定规则结合属性设置得到,对于没有对应特性的属性,只能使用getAttribute进行访问
e.getAttribute()返回值是源文件中设置的值,类型是字符串或者是null
e.propName返回值可能是字符串、布尔值、对象、undefined等
大部分attribute与property是一一对应关系,修改其中一个会影响另外一个,如id、title等属性
一些布尔属性的检测设置需要hasAttribute和removeAttribute来完成,或者设置对应的property
像link中的href属性,转换成property的时候需要通过转换得到完整的url
一些attribute和property不是一一对应,如:form控件中对应的是defaultValue,修改或设置value property修改的是控件当前值,setattribute修改value属性不会改变value property
offfsetWidth、offsetHeight返回值包含content+padding+border,效果与e.getBoundingClientRect()相同
clientWidth、clientHieight返回值值包含content+padding,如果有滚动条,也不包含滚动条
scrollWidth、scrollHeight返回值包含content+padding+溢出内容的尺寸
1、 focus/blur不冒泡,focusin/focusout冒泡
2、 focus/blur兼容性好,focusin、focusout在除fireFox外的浏览器下都保持良好兼容性,如需使用事件托管,可考虑FireFox下使用事件捕获
elem.addEventListener(‘focus’,handler,true)
3. 可获得焦点的元素:
window/链接被点击或键盘操作/表单控件被点击或键盘操作/设置tabindex属性的元素被点击或键盘操作
===为等同符,当左边与右边的值与类型都完全相等时,会返回true;
==为等值符,用来判断值是否相同,不会判断类型是否相同
addEventListener监听点击事件与click事件有什么区别?
addEventListener事件可以对普通元素进行多个事件处理,click事件只能使元素运行最新的事件结果
null用来表示尚未存在的对象,常用来表示函数企图返回一个不存在对象
undefined主要指定义了变量,但是并未赋值
NAN (not a Number)不是一个明确数值的数字类型
ECMAScript认为undefined是从null派生出来的,他们的值是一样的,但是类型却不一样。
所以
null == undefined //true
null === undefined //false
检查对象中存在某个属性的方式有三种:
第一种使用in操作符号, 返回true或false:
console.log(“属性名” in 对象名);
第二种使用hasOwnProperty方法, 会返回true或false:
console.log(对象.hasOwnProperty(“属性名”));
第三种是是够括号符号obj[‘属性名’], 如果属性存在, 则返回该属性的值, 如果不存在, 则返回undefined
splite():用于把一个字符串分割成字符串数组
search():用于减缩字符串中指定的子字符串,或检索与正则表达式相匹配的字符串
indexOf():可返回某个字符换字符串中首次出现的位置
substring():用于提取字符串中介于两个指定下标之间的字符
trim():移除字符串两边的空格
replace():替换字符
length:计算数组的长度
索引:通过索引获取数组中对应值,同时也可以改变索引对应的值
indexOf:返回指定元素的位置,若元素不存在返回-1
slice:接受1-2个参数,参数对应的是要返回的是要返回项的起始位置和结束位置,若只有一个参数,该方法返回从参数指定位置到数组结尾的所有项,如果还有两个参数,则返回起始位置到结束位置项,但是不包括结束位置项,返回的结果是一个新数组。
push:向数组末位添加若干元素,返回添加元素后数组的长度
pop:删除数组末位最后一个元素,但会被删除元素
unshift:向数组头部添加若干元素,返回添加元素后的数组长度
shift:删除数组头部的第一个元素,返回被删除的元素
sort:对数组进行排序,返回排序后的数组
reverse:对数组中的数据进行反转,返回反转后的数组
concat:将两个数组合并,返回新数组(可以接受任意元素和数组,并进行拆分放入数组)
join:将数组中的每一个元素用指定的字符串拼接起来
js的 for 跟for in 循环它们之间的区别?
遍历数组时的异同: for循环 数组下标的typeof类型:number, for in 循环数组下标的typeof类型:string;
var southSu = ['苏南','深圳','18','男'];for(var i=0;i<southSu.length;i++){
console.log(typeof i); //number
console.log(southSu[i]);// 苏南 , 深圳 , 18 , 男
}var arr = ['苏南','深圳','18','男','帅气',"@IT菲酵犯缌?-首席填坑官"];for(var k in arr){
console.log(typeof k);//string
console.log(arr[k]);// 苏南 , 深圳 , 18 , 男 , 帅气,平头哥联盟-首席填坑官
}
遍历对象时的异同:for循环 无法用于循环对象,获取不到obj.length; for in 循环遍历对象的属性时,原型链上的所有属性都将被访问,解决方案:使用hasOwnProperty方法过滤或Object.keys会返回自身可枚举属性组成的数组
Object.prototype.test = '原型链上的属性,本文由平头哥联盟-首席填坑官∙苏南分享';var southSu = {name:'苏南',address:'深圳',age:18,sex:'男',height:176};for(var i=0;i<southSu.length;i++){
console.log(typeof i); //空
console.log(southSu[i]);//空
}
for(var k in southSu){
console.log(typeof k);//string
console.log(southSu[k]);// 苏南 , 深圳 , 18 , 男 , 176 ,本文由平头哥联盟-首席填坑官∙苏南分享
}
push()、pop()、shift()、unshift()分别是什么功能?
push 方法 将新元素添加到一个数组中,并返回数组的新长度值。
var a=[1,2,3,4]; a.push(5);
pop 方法 移除数组中的最后一个元素并返回该元素。
var a=[1,2,3,4]; a.pop();
shift 方法 移除数组中的第一个元素并返回该元素。
var a=[1,2]; alert(a.shift());
unshift 方法 将指定的元素插入数组开始位置并返回该数组。
使用事件监听,可给一个DOM节点绑定多个事件(addEventListener)
拖拽会用到哪些事件?dragstart—拖拽开始时在被拖拽元素上触发此事件,监听器需要设置拖拽所需数据,操作系统拖拽文件到浏览器时不触发此事件
dragenter—拖拽鼠标进入元素时在该元素上触发,用于给拖放的元素设置视觉反馈,如高亮
dragover—拖拽时鼠标在目标元素上移动时触发,监听器通过组织浏览器默认行为设置元素为可拖放元素
dragleave—拖拽时鼠标移出目标元素时在目标元素上触发,此时监听器可以取消掉前面设置的视觉效果
drag—拖拽期间在被拖拽元素上连续触发
drop—鼠标在拖放目标上释放时,在拖放目标上触发,此时监听器需要收集数据并且执行所需操作,如果是从操作系统拖放文件到浏览器,需要取消浏览器默认行为
dragend—鼠标在拖放目标上释放时,在拖拽元素上触发,将元素从浏览器拖放到操作系统时不会触发此事件
setTimeout 只执行一次
setInterval 会一直重复执行
document.write是直接写入到页面的内容流,如果在写之前没有调用document.open,浏览器会自动调用open。每次写完关闭后重新调用该函数,会导致页面被重写
innerHTML则是DOM页面元素的一个属性,代表该元素的html内容,你可以精确到某一个具体的元素来进行更改。如果想修改document的内容,则需要修改document.documentElement.innerElement
innerHTML将内容写入某个DOM节点,不会导致页面全部重绘,innerHTML很多情况下都优于document.write,其原因在于其允许更精准的控制要刷新页面的那个部分
共同点:
添加子元素后返回值都是新添加的子元素 都可以通过appendChild添加子元素,并且子元素必须是node类型,不能为文本 若添加的子元素是文档中存在的元素,则通过appendChild在为其添加子元素时,会从文档中删除之存在的元素使用Fragment(document.createDocumentFragment( ))
Documentfragments是DOM节点,它们不是DOM树的一部分。通常的用例是创建文档片段,将元素附加到文档片段,然后将文档片段附加到DOM树中。因为文档片段存在于内存中,并不在DOM树中,所以讲子元素插入到文档片段时不会引起页面回流。因为使用文档片段会带来更好的性能
先创建一个div,后续的复制这个元素,避免重复创建元素,再放到元素片段里面
var divFragment = document.createDocumentFragment();
let div = document.createElement(“div”);
for(var i = 0; i <1000; i ++){
divFragment.append(div.cloneNode())
}
document.body.appendChild(divFragment);
JS中几种常见的高阶函数
高阶函数是对其他函数进行操作的函数,可以将它们作为参数或通过返回它们。简单来说,高阶函数是一个函数,它接收函数作为参数或将函数作为输出返回。
typeof和instanceof有什么区别?typyof用于判断数据的基本类型
instanceof用于判断一个变量是够属于某个对象的实例。也可以用来判断某个构造函数的prototype属性是否存在另外一个要检测对象的原型链上
同步就是指一个进程在执行某个请求的时候,若该请求需要一段时间才能返回信息,那么这个进程将会一直等待下去,直到返回信息之后才继续执行后面的代码
异步是指进程不需要一直等下去,而是继续执行下面的操作,不管其他进程的状态。当有消息返回时系统会通知进程进行处理,这样可以提高执行的效率。
window.onload和DOMContentLoaded的区别
window.addEventListener(‘load’,function(){
//页面的所有资源加载完才会执行, 包括图片和视频等
})
document.addEventListener(‘DOMContentLoaded’,function(){
//DOM渲染完即可执行, 此时图片,视频还可能没有加载完成
})
document.load和document.redy的区别?
load是当页面所有资源加载完成后(包括DOM文档树,css文件,js文件,图片资源等),执行一个函数进程:是资源分配的基本单词,它是程序执行时的一个实例。程序运行时系统就会创建一个进程,并为它分配CPU时间,程序开始真正运行。
线程:是程序执行时的最小单位,它是进程的一个执行流,是CPU调度和分配的基本单位,一个进程可以由很多个线程组成,线程间共享进程的所有资源,每个线程有自己的堆栈和局部变量。线程由CPU独立调度执行,在多CPU环境下九允许多个线程同时运行。同样多线程也可以实现并发操作,每个请求分配一个线程来处理。
伪数组:无法直接调用数组方法或期望length属性有什么特殊的行为,不具有push、pop等方法,但仍可以对真正数组遍历方法来遍历它们。典型的是函数的argument参数等
伪数组的三大特性:
console.log( arr instanceof Array )
console.log( arr.construct == Array)
console.log( Array.isArray( arr ))
cancelBunnle(IE)
return false;
event.preventDefault( );
event.stopPropagation( );
标记清楚:这是js最常用的垃圾回收方法,当一个变量进入执行环境时,例如函数中声明一个变量,将其标记为进入环境,当变量离开环境时,(函数执行结束),标记为离开环境
引用计数:跟踪记录每个值被引用的次数,声明一个变量,并将引用类型复制给这个变量,则这个值的引用次数+1,当变量的值变成了另一个,则这个值的引用次数-1,当这个值的引用次数为0的时候,就回收
//方式1
function A(){};
function B(){};
B.prototype = new A()
//方式2
function A(){};
function B(){
A.call(this);
};
// 方式3
function A(){};
function B(){};
B.prototype = new A();
function B(){
A.call(this)
}
mouseover和mouseenter的区别
mouseover:当鼠标移入元素或其子元素都会触发事件,所以有一个重复触发冒泡的过程
mouseenter:当鼠标移入元素(除了元素本身, 不包含子元素)会触发的事件
clientHeight: 表示的是可视区域的高度, 不包含border和滚动条
offsetHeight: 表示可是区域的高度, 包含了border和滚动条
scrollHeight: 表示了所有区域的高度, 包含了滚动条被隐藏的部分
clientTop: 表示边框border的厚度, 在为指定的情况下,一般为0
scrollTop: 滚动后被隐藏的高度, 获取对象相对于offsetParent属性指定的父坐标距离顶部的距离
展开(Spread)运算符和剩余(Rest)运算符有什么区别?
展开运算符(spread)是三个点(…),可以将一个数组转为用逗号分隔的参数序列。说的通俗易懂一点,有点像化骨绵掌,把一个大元素给打散成一个个单独的小元素
剩余运算符也是用三个点(…)表示, 它的样子看起来和展开运算符一样,但是它是用于结构数组和对象. 在某种程度上, 剩余元素和展开元素相反, 展开元素会”展开”数组变成多个元素, 剩余元素会收集多个元素和”压缩”成一个单一的元素
// 拓展运算符
let arr = ["阿里巴巴",'阿里妈妈','蚂蚁金服'];`在这里插入代码片`
console.log(...arr); //阿里巴巴 阿里妈妈 蚂蚁金服
//剩余运算符
let [webName,...rest] = ["阿里巴巴",'阿里妈妈','蚂蚁金服'];
console.log(webName); //阿里巴巴
console.log(rest); //(2) ["阿里妈妈", "蚂蚁金服"]
程序菜小猿
原创文章 3获赞 5访问量 520
关注
私信
展开阅读全文