前言
最近在读《javascript高级程序设计》疏通经脉,通过写文的方式加强自己理解。
函数方法
在前端面试的问题中少不了this
指向的问题,而以下三种方法都可以改变this
指向:
- apply()
- call()
- bind()
1. apply方法
apply()
和call()
两个方法的用途都是在特定的作用域中调用函数,实际上等于设置函数体内的this
对象的值。apply()
方法接受两个参数:
- 第一个参数:
thisArg
thisArg
该参数可选填,在func 函数
运行时使用的this
值。如果这个函数处于非严格模式下,则指定为null
或undefined
时会自动替换为指向全局对象,原始值会被包装。如果该参数缺失时则指向全局对象。
- 第二个参数:
argsArray
argsArray
该参数可选填,接受一个数组或arguments(arguments知识传送门:javascript:函数属性梳理)。如果不填写则代表不需要传参。
let o1 = {
number: 100
}
let o2 = {
number: 200
}
function sum (num1, num2) {
console.log(num1 + num2 + this.number)
}
sum.apply(o1, [1, 10]) // 111 将this指向o1
sum.apply(o2, [1, 10]) // 211 将this指向o2
apply()
不仅能传参,最重要的是能够改变函数赖以运行的作用域!!!在上面的例子中,当传入o1
时,this.number
指向了o1
里的number
;当传入o2
时,this.number
指向了o2
里的number
。
2. call方法
理解了
apply()
,那理解call()
便不费吹灰之力。因为call()
与apply()
方法唯一的区别在于第二个参 接受参数的形式不同,作用完全相同。call()传递给函数的参数只能逐个列举出来,看下面的例子:
function sum (num1, num2) {
console.log(num1 + num2)
}
sum.call(o1, 1, 10) // 11
3. bind方法
bind()
方法创建一个新的函数,在调用时设置this
关键字为提供的值。并在调用新函数时,将给定参数列表作为原函数的参数序列的前若干项。和call()
与apply()
的区别在于:bind()
会创建一个原函数的拷贝
(绑定函数),拥有指定的this
值和初始参数,并返回这个函数。看下MDN里的描述:
bind()
最简单的用法是创建一个函数,不论怎么调用,这个函数都有同样的this
值。JavaScript
新手经常犯的一个错误是将一个方法从对象中拿出来,然后再调用,期望方法中的this
是原来的对象(比如在回调中传入这个方法)。如果不做特殊处理的话,一般会丢失原来的对象。基于这个函数,用原始的对象创建一个绑定函数,巧妙地解决了这个问题:
this.x = 9; // 在浏览器中,this指向全局的 "window" 对象
var module = {
x: 81,
getX: function() { return this.x; }
};
module.getX(); // 81
var retrieveX = module.getX;
retrieveX();
// 返回9 - 因为函数是在全局作用域中调用的
// 创建一个新函数,把 'this' 绑定到 module 对象
// 新手可能会将全局变量 x 与 module 的属性 x 混淆
var boundGetX = retrieveX.bind(module);
boundGetX(); // 81
结语
关于call、apply和bind函数的作用极其相似,但有不同之处,关于如何更好运用还得在探索。
参考资料:
- 《javascript高级程序设计》
- MDN--bind
种一棵树最好的时间是十年前。