- call call的特点
- 可以改变当前函数this的指向
- 让当前函数执行
function fn1(){
console.log(this)
}
fn1.call()
结果是:window
复制代码
如果传值
function fn1(){
console.log(this,arguments)
}
fn1.call('jeffywin',1,2)
结果是:jeffywin,Arguments(2)[1,2]
复制代码
function fn1() {
console.log(1)
}
function fn2() {
console.log(2)
}
//fn1的this指向fn2,并且让fn1执行
fn1.call(fn2)
结果是:1,this指向fn2
复制代码
原理类似于
Function.prototype.call = function(context) {
this() //会让当前函数的this指向fn2,fn2执行
}
fn1.call.call(fn2)
结果是:2
复制代码
Function.prototype.callBind = function(context) {
context = context ? Object(context) : window
//context: hello 上下文
//arguments ['hello',1,2]
//this = fn1()
//如果要让this='hello',fn1执行的时候,xxx.fn1() .前面是谁,this就指向谁,这里context上下文就是hello
//所以让context转成对象,(字符串不能.fn1())再挂上fn1(),这样this就指向hello
//eval('context.fn('+args+')')执行的时候,因为context.fn = fn1,所以context.fn()执行相当于fn1执行,this指向context,也就是hello
context.fn = this //{}.fn = fn1 context.fn=fn1
let args = []
for(let i=1;i<arguments.length;i++) {
args.push('arguments['+i+']')
}
//context.fn(arguments[1],arguments[2])
//eval() 函数可计算某个字符串,并执行其中的的 JavaScript 代码。
let r = eval('context.fn('+args+')')
delete context.fn
return r
}
fn1.callBind('hello',1,2)
复制代码
//apply实现
Function.prototype.applyBind = function(context,args) {
context = context ? Object(context) : window
context.fn = this
if(!args) {
return context.fn()
}
let r = eval('context.fn('+args+')')
delete context.fn
return r
}
fn1.applyBind('hello',[1,2])
复制代码
//1) bind方法可以绑定this指向 绑定参数
//2) bind方法返回一个绑定后的函数 原理:高阶函数
//3) 如果绑定的函数被new了,当前函数的this就是当前的实例
//4) new 出来的结果可以找出原有类的原型
Function.prototype.bindMy = function (context) {
let that = this;
let bindArgs = Array.prototype.slice.call(arguments, 1);//['猫']
//this:fn context:obj
function Fn(){}
function fBound() {
let args = Array.prototype.slice.call(arguments)
return that.apply(this instanceof fBound ? this : context, bindArgs.concat(args))
}
Fn.prototype = this.prototype
fBound.prototype = new Fn()
return fBound
}
let obj = {
name: 'jeffywin'
}
function fn(name, age) {
console.log(this.name + '养了一只' + name + age + '岁了')
}
fn.prototype.flag="哺乳类"
let bindFn = fn.bindMy(obj, '猫')
//bindFn(9)
let i = new bindFn(9)
console.log(i.flag)
复制代码