Function.prototype及call/apply/bind
Function.prototype & Object.prototype
Function:
- 所有的类(包括内置类)都是函数,每一个函数都是Function的一个实例,所以他们的__proto__一定指向的是Function.prototype
- 所有的函数都天生自带一个属性:prototype,这个属性指向当前实例所属类的原型
- Function.prototype是一个对象,天生自带一个属性constructor,指向当前类
Object:
- 每一个对象都是Object的实例,所以最后他们基于__proto__一定可以找到Object.prototype。
Function.prototype
- apply: ƒ apply()
- arguments:
- bind:
- call:
- caller:
- constructor:
- length:
- name:
- toString:
- __proto__: Object
- …
数组的面向对象原型图
Array(内置数组类):所有的类都是函数,所有的函数都天生自带一个属性:prototype,所有的函数也是对象,会天生自带一个属性 – __proto__,所有的函数都是大写Function这个类的一个实例,Array.prototype是一个对象
let arr = [10, 20, 30];
首先,arr是Array的实例,Array是一个类(数组内置类,类都是函数数据类型的),内部存着 “[native code]”(内置代码不允许我们查看),数组也是对象(特殊对象)。
Array的常用属性:
- length:
- new Array([num]): 参数位数字,代表创建一个长度为num的数组,参数为数字0或者不传参数,都是创建一个空数组
- new Array(“num1”,“num2”,…), 参数为非数字,代表创建一个数组,数组元素为参数。
- from: 把类数组转换为数组
- isArray: 检测是否为数组
- name: “Array”
- prototype:所有的类都是函数,天生自带这个属性,是一个对象,数组中常用的方法都存储在原型上。
- __proto__ : 所有的对象都自带这个属性,代表原型链
- …
call/apply/bind
- call/apply/bind 三者的区别
- call应用:把类数组转换为数组
- apply应用:获取数组中的最大值
重写CALL方法
~ function () {
function call(context) {
context = context || window;
let args = [].slice.call(arguments,1),
result;
context.$fn = this;
result = context.$fn(...args);
delete context.$fn;
return result;
}
Function.prototype.call = call;
}();
重写BIND方法
~function(proto){
function bind(context=window,...outerArgs){
let _this=this;
return function(...innerArgs){
let args=outerArgs.concat(innerArgs);
_this.call(context,...args);
}
}
proto.bind = bind;
}(Function.prototype);
面试题
function fn1(){console.log(1);}
function fn2(){console.log(2);}
fn1.call(fn2);
fn1.call.call(fn2);
Function.prototype.call(fn1);
Function.prototype.call.call(fn1);