序言:
作為一名合格的前端開發者,大家都應該知道改變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上下文的方法,助力源碼閱讀。
