JavaScript高阶面试题:(第一天)
目录
1.什么是原型,什么是原型链?
2.call / apply / bind 有啥区别
3.JS四种检测数据类型的方式
4.说说继承
5.for..in和for..of和forEach的区别
1.什么是原型,什么是原型链?
原型:
每一个构造函数,都会有一个 prototype
属性。该属性指向一个对象,该对象称之为 原型对象
,即原型。
原型链:
当访问一个对象的某个属性时,会先在这个对象本身属性上查找,如果没有找到,则会去它的__proto__
上查找,即它的构造函数的prototype,如果还没有找到就会再在构造函数的prototype的__proto__
中查找(即上一层构造函数的prototype),这样一层一层向上查找直到Object的prototype结束,这样就会形成一个链式结构,我们称为原型链。我们可以说:它们是继承关系
2.call / apply / bind 有啥区别
call:
call(thisObj, arg1, arg2...)
要求传入函数的参数是参数列表
apply:
apply(thisObj, [argArray])
要求传入函数的参数必须放入数组中整体传入
bind:
bind(thisObj,arg1,arg2,...)
- 共同点 : 都可以改变this指向
- 不同点:
-
- call 和 apply会立即调用函数.bind不会立即调用函数, 需要手动调用.
- call及bind 和 apply传递的参数不一样,call及bind传递参数使用逗号隔开,apply使用数组传递.
- 应用场景
-
- call 经常做继承.
- apply 经常跟数组有关系. 比如借助于数学对象实现数组最大值最小值
- bind 不调用函数,但是还想改变this指向. 比如改变定时器内部的this指向.
3.JS四种检测数据类型的方式
1.typeOf :只能检测基本数据类型
2.instanceOf :检测当前实例是否属于某个类的方法
3.constructor: 检测当前实例的构造函数
4.Object.prototype.toString.call( ) : 最准确的方式;
4.说说继承
- 构造函数继承(在子类的构造函数中执行父类的构造函数,并为其绑定子类的this,让父类的构造函数把成员属性和方法都挂到子类的this上)
缺点:无法访问原型上的方法 - 原型链继承(将子构造函数的原型对象指向父构造函数的实例,让constructor 重新指向子构造函数)
缺点:无法为不同的实例初始化继承来的属性 - 组合式继承(将原型链继承和构造函数继承组合到一起, 综合了原型链继承和构造函数继承的优点)
缺点:调用了两次父类构造函数 - 原型式继承(Object.create():这个方法接收两个参数:一是用作新对象原型的对象、二是为新对象定义额外属性的对象(可选参数),核心思想:使用一个中间函数,连接父类与子类的关系。借助原型可以基于已有的对象创建新对象,同时还不必因此创建自定义类型。)
- extends继承(class和extends是es6新增的,class创建一个类,extends实现继承)
可参照文档:JS中常用实现继承的方法(Object.create的原理)_object.create原理-CSDN博客
5.for..in和for..of和forEach的区别
for ..in:
可以循环数组也能循环对象,循环遍历的值是数据结构的键值;
可以使用return、break、continue中断循环;
在有些情况下会以随机顺序遍历数组,所以最好用来遍历对象;
for ..of:
可以循环可迭代对象(如数组、字符串等),循环遍历的值是数据结构的值;
可以使用return、break、continue中断循环;
forEach:
在回调函数内部有三个参数:item、index、arr分别表示当前项、当前项的索引下标、数组本身;
会对数组的每一个元素执行一次提供的函数,不改变原数组、没有返回值(undefined);