# this, call 和 apply

this 关键字和其他语言最大的区别是,他总是指向一个对象。并且在函数运行时基于当前函数的执行环境动态绑定的。

var obj = {
    num: 1,
    count() {
      console.log(this)
      return this.num;
    }
}
obj.count() // 1

// 由于执行环境不同,this 指向了 widnow
var count = obj.count
count() // undefined

但是在严格模式下 'use strict' this 的指向又会变为 undefined。这就是 this 丢失。

;(function() {
    console.log(this); // window
})();

;(function() {
    'use strict'
    console.log(this); // undefined 严格模式
})();

call 和 apply 这两个函数都是用来修改函数的 this 指向。他们都属于 Function 对象,这说明每个函数都有这两方法可以调用。

当函数调用了 call 和 apply 时,都会立刻执行这个函数。

call 和 apply 的第一个参数都是 this,第二个参数有所不同:

var f = function(age, work) {
  console.log(`我叫:${this.name}, 今年 ${age} 岁, 职业: ${work}`)
}
let o = {
  name: '石兴龙'
}

// 我叫:石兴龙, 今年 18 岁, 职业: web前端开发者
f.call(o, 18, 'web前端开发者')
// 我叫:石兴龙, 今年 18 岁, 职业: web前端开发者
f.apply(o, [18, 'web前端开发者'])
// 我叫:石兴龙, 今年 18 岁, 职业: web前端开发者

f = f.bind(o, 18, 'web前端开发者')
// 我叫:石兴龙, 今年 18 岁, 职业: web前端开发者
f();

# call 和 apply 的区别

call 和 apply 都是非常常用的方法。区别在于传入参数的形式不同。

call 第一个是 this 的指向,的第二个之后的参数是函数的参数列表,一般用于参数不确定的函数

apply 接受两个参数。第一个是this的指向,第二个是一个数组,这个数字将被当做被调用的函数的参数列表

在刚刚的例子中,我们还看到了 bind 函数。这其实是 call 的变种。bind 接受参数的方式和 call 是一样的。唯一的区别是他并不会立即执行,而是返回一个已经被修改过 this 的函数。我们可以来尝试手动实现一个 bind 函数。

Function.prototype.bind = function(o) {
    var self = this
    var bindArgs = arguments
    return function() {
        var args = []
        for (var i = 1; i < bindArgs.length; i++) {
            args.push(bindArgs[i])
        }
        for (var i = 0; i < arguments.length; i++) {
            args.push(arguments[i])
        }
        return self.apply(o, args)
    }
}
f = f.bind(o, 18, 'web前端开发者')
f();
上次更新: 8/5/2020, 12:21:17 AM