call
函数
- 特点:
- 1)可以改变我们当前函数的this指向
- 2)还会让当前函数执行
Function.prototype.call = function (context) {
if (typeof this !== 'function') {
throw new TypeError(`${this} is not a function`)
}
context = Object(context) || window;
context.fn = this;
let args = [];
for (let i = 1; i < arguments.length; i++) {
args.push('arguments['+i+']');
}
let r = eval('context.fn('+args+')');
delete context.fn;
return r;
}
复制代码
题目自测
function fn1() {
console.log(this,arguments);
console.log(1);
}
function fn2() {
console.log(this,arguments);
console.log(2);
}
fn1.call(fn2,1,2);
fn1.call.call.call.call.call(fn2,1,2);
复制代码
- 思路解析
-
fn1.call(fn2,1,2)
- 1)
call
执行传入fn2
,1
,2
三个参数
- 2)
call
函数内部context = Object(fn2) = fn2
- 3)
fn2.fn = fn1
- 4)
args=['arguments[1]','arguments[2]']=[1,2]
- 5)
eval('context.fn('+args+')') = fn2.fn(1,2) = fn2.fn1(1,2)
-
fn1.call.call.call.call.call(fn2,1,2)
- 1)
call
执行传入fn2
,1
,2
三个参数
- 2)
call
函数内部context = Object(fn2) = fn2
- 3)
fn2.fn = call
- 4)
args=['arguments[1]',arguments[2]]=[1,2]
- 5)
eval('context.fn('+args+')') = fn2.fn(1,2) = fn2.call(1,2)
- 6)
call
执行传入1
,2
两个参数
- 7)
call
函数内部context = Object(1) = Number{1}
- 8)
Number{1}.fn = fn2
- 9)
args=['arguments[1]']=[1]
- 10)
eval('context.fn('+args+')') = Number{1}.fn(2) = Number{1}.fn2(2)
- 注:多次调用
call
的时候其实是call
执行的时候内部又调用了一次call
,总共调用两次
apply
函数
- 特点:
- 1)可以改变我们当前函数的this指向
- 2)还会让当前函数执行
Function.prototype.apply = function (context,args) {
if (typeof this !== 'function') {
throw new TypeError(`${this} is not a function`)
}
context = Object(context) || window;
context.fn = this;
if(!args){
return context.fn();
}
let r = eval('context.fn('+args+')');
delete context.fn;
return r;
}
复制代码
new
操作符
- 特点
- 新生成了对象
- 链接到原型
- 绑定
this
- 返回一个对象
function Animal(type) {
this.type = type ;
}
Animal.prototype.say = function () {
console.log('say');
}
let tiger = new Animal('tiger');
console.log(tiger);
--------------------------------------------------------
function mockNew(){
let Constructor = [].shift.call(arguments);
let obj = {};
obj.__proto__ = Constructor.prototype;
let r = Constructor.apply(obj,arguments)
return r instance Object ? r : obj;
}
let tiger = mockNew(Animal,'tiger');
console.log(tiger);
复制代码
bind
函数
- 特点
- 绑定
this
指向
- 返回一个绑定后的函数(高阶函数原理)
- 如果绑定的函数被
new
执行 ,当前函数的this
就是当前的实例
-
new
出来的结果可以找到原有类的原型
Function.prototype.bind = function (context) {
if (typeof this !== 'function') {
throw new TypeError(`${this} is not a function`)
}
let that = this;
let bindArgs = Array.prototype.slice.call(arguments, 1);
function Fn() { };
function bindFn() {
let args = Array.prototype.slice.call(arguments);
that.apply(this instanceof bindFn ? this : context, bindArgs.concat(args));
}
Fn.prototype = that.prototype;
bindFn.prototype = new Fn();
return bindFn;
}
复制代码