JavaScript中改变context上下文的方法
序言:
作为一名合格的前端开发者,大家都应该知道改变js作用域中上下文的方法有:call、apply和bind。思考一个问题:还有没有更好的实现方式呢?
1、call和apply
call和apply是最简单实现改变函数体内部this指向的方法,他们的区别仅仅是第二个参数不同。语法示例:
obj.call(thisObj,arg1,agr2,...)
obj.apply(thisObj,[arg1,agr2])
代码示例(Math.max)
Math.max(1, 3, 2)
如输入参数是数组呢?
Math.max.apply(null,[1,2,3,4,2,3])
说明:上面示例代码中,第一个参数为null,也可以为其他(空字符串,对象),仅仅是“借用”Math的max方法而已。
2、bind
bind方法是创建一个新方法,当函数调用时将this设置为提供的值。与call类似,除第一个参数外是可变参数,语法示例:
obj.bind(thisObj,arg1,agr2,...)
这时thisObj就有了obj方法和属性。
bind与call和apply不同的是,bind之后返回一个函数,不会立即执行。需要再显示执行一次才能完成函数的调用。如:
let m = test.bind(obj,3)
m()
另外,bind也常用在ES6的Class绑定上下文。
class Dog {
constructor() {
this.name = 'adong';
}
start() {
this.p().then(this.say);
}
p() {
return new Promise((resolve, reject)=>{
resolve('good');
})
}
say(str) {
console.log(this);
console.log(this.name + str);
}
}
let dog = new Dog();
dog.start();
上述代码会显示:
即在Promise的then方法参数是一个匿名函数,匿名函数的this指向是:undefined。
这里有2种方案:
(1)箭头函数
class Dog {
constructor() {
this.name = 'adong';
}
start() {
this.p().then(this.say);
}
p() {
return new Promise((resolve, reject)=>{
resolve('good');
})
}
say= (str) => {
console.log(this);
console.log(this.name + str);
}
}
let dog = new Dog();
dog.start();
即,使用箭头函数,this执行函数定义时作用域,即Dog对象
(2)使用bind绑定this指向
class Dog {
constructor() {
this.name = 'adong';
}
start() {
this.p().then(this.say.bind(this));
}
p() {
return new Promise((resolve, reject)=>{
resolve('good');
})
}
say(str) {
console.log(this);
console.log(this.name + str);
}
}
let dog = new Dog();
dog.start();
3、使用ES7的Decorators
使用autobind-decorator库,实现自动this绑定。
import autobind from 'autobind-decorator'
class MathTest {
constructor(val) {
this.val = val
}
@autobind
show() {
return this.val
}
}
let mathTest = new mathTest(42);
let show = mathTest.show;
show()
当然@autobind也可以在整个类上进行this上下文的绑定。
4、双冒号运算符
双冒号左边是一个对象,右边是一个函数。该运算符会自动将左边的对象,作为上下文环境(即this对象),绑定到右边的函数上面。
示例代码:
[1,2,3]::Array.prototype.map(x=>{return x*3})
经过babel编译后:
"use strict";
var _context;
(_context = [1, 2, 3], Array.prototype.map).call(_context, function (x) {
return x * 3;
});
即对象[1,2,3]作为this绑定到了Array的map方法上。
5、总结
以上即是js中绑定this上下文的方法,助力源码阅读。
作者:孟繁贵 Email:meng010387@126.com 期待共同进步!