js面试题

2019-02-19  本文已影响0人  symY_Y
1,js的深拷贝与浅拷贝

如何区分深拷贝与浅拷贝,简单点来说,就是假设B复制了A,当修改A时,看B是否会发生变化,如果B也跟着变了,说明这是浅拷贝,拿人手短,如果B没变,那就是深拷贝,自食其力。
深拷贝:1,可以使用递归去复制所有层级属性
2,使用JSON对象的parse和stringify
3,使用JQ的extend方法:$.extend( [deep ], target, object1 [, objectN ] )
deep表示是否深拷贝,为true为深拷贝,为false,则为浅拷贝
target Object类型 目标对象,其他对象的成员属性将被附加到该对象上。
object1 objectN可选。 Object类型 第一个以及第N个被合并的对象。

2,json和js对象的区别

总而言之你可以理解为JSON是JS下的一种数据格式,他从属于JS,并且在处理JSON数据时可直接使用JS内置API

1550540329990.jpg
3,jsonp原理详解

Jsonp(JSON with Padding) 是 json 的一种"使用模式",可以让网页从别的域名(网站)那获取资料,即跨域读取数据
JSONP是一种非官方跨域数据交互协议,该协议的一个要点就是允许用户传递一个callback参数给服务端,然后服务端返回数据时会将这个callback参数作为函数名来包裹住JSON数据,这样客户端就可以随意定制自己的函数来自动处理返回数据了。

4,同源策略,js跨域解决方案

同源策略:同协议,同域名和同端口
1、 通过jsonp跨域:只能实现get一种请求
2、 document.domain + iframe跨域:仅限主域相同,子域不同的跨域应用场景
原理:两个页面都通过js强制设置document.domain为基础主域,就实现了同域。
3、 location.hash + iframe
原理:a欲与b跨域相互通信,通过中间页c来实现。 三个页面,不同域之间利用iframe的location.hash传值,相同域之间直接js访问来通信。
4、 window.name + iframe跨域
window.name属性的独特之处:name值在不同的页面(甚至不同域名)加载后依旧存在,并且可以支持非常长的 name 值(2MB)。
5、 postMessage跨域
6、 跨域资源共享(CORS)
7、 nginx代理跨域
8、 nodejs中间件代理跨域
9、 WebSocket协议跨域
详细地址:https://segmentfault.com/a/1190000011145364

5,JavaScript事件代理(先捕获再冒泡)

JavaScript事件代理:把事件处理器添加到一个元素上,等待一个事件从它的子级元素里冒泡上来,并且可以得知这个事件是从哪个元素开始的。
事件捕获:当某个元素触发某个事件(如onclick),顶层对象document就会发出一个事件流,随着DOM树的节点向目标元素节点流去,直到到达事件真正发生的目标元素。在这个过程中,事件相应的监听函数是不会被触发的。
事件目标:当到达目标元素之后,执行目标元素该事件相应的处理函数。如果没有绑定监听函数,那就不执行。
事件冒泡:从目标元素开始,往顶层元素传播。途中如果有节点绑定了相应的事件处理函数,这些函数都会被一次触发。如果想阻止事件起泡,可以使用e.stopPropagation()(Firefox)或者e.cancelBubble=true(IE)来组织事件的冒泡传播。

6,call和apply的作用和区别

call 与 apply的定义
apply:调用一个对象的一个方法,用另一个对象替换当前对象。
例如:B.apply(A, arguments);即A对象应用B对象的方法。
call:调用一个对象的一个方法,用另一个对象替换当前对象。
例如:B.call(A, args1,args2);即A对象调用B对象的方法。
call 与 apply 的相同点
1,方法的含义是一样的,即方法功能是一样的;
2,第一个参数的作用是一样的;
call 与 apply 的不同点:两者传入的列表形式不一样
1,call可以传入多个参数;
2,apply只能传入两个参数,所以其第二个参数往往是作为数组形式传入
存在的意义:实现(多重)继承

7,原型继承原理以及实现继承的方法

原型继承原理
原型链是实现原型继承的主要方法,基本思想就是利用原型让一个引用类型继承另一个引用类型的属性和方法。
实现继承的方法
1、原型链继承: (将父类的实例作为子类的原型)
特点:
-1. 非常纯粹的继承关系,实例是子类的实例,也是父类的实例;
-2. 父类新增原型方法/原型属性,子类都能访问到;
-3. 简单,易于实现;
缺点:
-1. 要想为子类新增属性和方法,必须要在new Animal()这样的语句之后执行,不能放到构造器中;
-2. 无法实现多继承;
-3. 来自原型对象的所有属性被所有实例共享(来自原型对象的引用属性是所有实例共享的)(详细请看附录代码: 示例1);
-4. 创建子类实例时,无法向父类构造函数传参;
2、构造继承:(使用父类的构造函数来增强子类实例,等于是复制父类的实例属性给子类(没用到原型))
特点:
-1,解决了1中,子类实例共享父类引用属性的问题
-2,创建子类实例时,可以向父类传递参数
-3,可以实现多继承(call多个父类对象)
缺点:
-1,实例并不是父类的实例,只是子类的实例
-2,只能继承父类的实例属性和方法,不能继承原型属性/方法
-3,无法实现函数复用,每个子类都有父类实例函数的副本,影响性能
3、实例继承:(为父类实例添加新特性,作为子类实例返回)
特点:
-1,不限制调用方式,不管是new 子类()还是子类(),返回的对象具有相同的效果
缺点:
-1,实例是父类的实例,不是子类的实例
-2,不支持多继承
4、拷贝继承
特点:
-1,支持多继承
缺点:
-1,效率较低,内存占用高(因为要拷贝父类的属性)
-2,无法获取父类不可枚举的方法(不可枚举方法,不能使用for in 访问到)
5、组合继承:(通过调用父类构造,继承父类的属性并保留传参的优点,然后通过将父类实例作为子类原型,实现函数复用)
特点:
-1,弥补了方式2的缺陷,可以继承实例属性/方法,也可以继承原型属性/方法
-2,既是子类的实例,也是父类的实例
-3,不存在引用属性共享问题
-4,可传参
-5,函数可复用
缺点:
-1,调用了两次父类构造函数,生成了两份实例(子类实例将子类原型上的那份屏蔽了)
6、寄生组合继承:(通过寄生方式,砍掉父类的实例属性,这样,在调用两次父类的构造的时候,就不会初始化两次实例方法/属性,避免的组合继承的缺点)
特点:
-1,堪称完美
缺点:
-1,实现较为复杂
参考链接:https://www.cnblogs.com/humin/p/4556820.html

7,DOM事件包括哪几个阶段?

事件冒泡阶段,事件目标阶段,事件捕获阶段

8,事件委托的实现原理?有什么优势和缺点?

原理是事件冒泡机制
优点:1.可以大量节省内存占用,减少事件注册。比如ul上代理所有li的click事件就很不错。
2.可以实现当新增子对象时,无需再对其进行事件绑定,对于动态内容部分尤为合适
缺点:事件代理的常用应用应该仅限于上述需求,如果把所有事件都用事件代理,可能会出现事件误判。即本不该被触发的事件被绑定上了事件

9,什么是原型链?什么是作用域链?分别有什么作用?

原型链:每个继承父函数的子函数的对象都包含一个内部属性proto。该属性包含一个指针,指向父函数的prototype,若父函数的原型对象的proto属性为再上一层函数,在此过程中就形成了原型链。
原型链作用:原型链实现了继承
原型链存在两个问题:
a 包含引用类型值的原型属性会被所有实例共享。
b在创建子类型时,无法向超类型的构造函数中传递参数。
作用域链:每一个函数都有一个作用域, 如果一个函数内部又嵌套链另外一个函数,嵌套的函数也会又一个作用域,这样,嵌套函数就能访问到外部函数中的变量,以及全局作用域中的变量,此时就形成了一条作用域链
作用域链相关知识的总结:
1.执行环境决定了变量的生命周期,以及哪部分代码可以访问其中变量
2,执行环境有全局执行环境(全局环境)和局部执行环境之分。
3.每次进入一个新的执行环境,都会创建一个用于搜索变量和函数的作用域链
4.函数的局部环境可以访问函数作用域中的变量和函数,也可以访问其父环境,乃至全局环境中的变量和环境。
5.全局环境只能访问全局环境中定义的变量和函数,不能直接访问局部环境中的任何数据。
6.变量的执行环境有助于确定应该合适释放内存。

10,事件循环(Event Loop)的机制是什么?
上一篇下一篇

猜你喜欢

热点阅读