前言
前些日子,在掘金上看到一片热门文章《在酷家乐做面试官的日子》。该文作者以面试官的角度,详细阐述了作为一名 web 应聘者应该具有哪些技能,才会更让人青睐。
在对比自身的过程中,发现有一些问题,或许了解,但不全面,这也是本系列文章诞生的缘由。
this 的定义
在 ECMAScript 这样定义的 this
The this keyword evaluates to the value of the ThisBinding of the current execution context
记住一个原则就好:
this 指向调用它的对象(谁污染,谁治理)。
this 的指向
使用 new 操作符
/*
* 谁调用 func,this 就是谁
* 当前运行时,是 obj 实例化了 func,所以 this 指向 obj
*/
function func(){
console.log(this.obj)
}
var obj = { obj: 'obj', func1 : new func()}
console.log(obj.msg) => hello world
使用 call、apply、bind
call、apply 和 bind 都会改变函数运行时的上下文。
在示例代码中,this 都指向第一个参数(调用者)
/*
* TODO:
* call、apply、bind 后期会有系列文章说明
*/
function func(){
console.log(this)
}
var obj1 = { msg : '1', obj: 'obj1' }
var obj2 = { msg : '2', obj: 'obj1' }
var obj3 = { msg : '3', obj: 'obj1' }
// 直接调用时,调用者是 window,this 指向 window。
func() => Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, parent: Window, …}
// 使用 call、apply 用于改变函数运行时的上下文
// 调用者是当前对象,指向当前对象
func.call(obj1) => {msg: "1", obj: "obj1"}
func.apply(obj2) => {msg: "2", obj: "obj1"}
// bind 和 call、apply 有细微不同, bind 的返回值是函数
func.bind(obj3)() => {msg: "3", obj: "obj1"}
ES6 的箭头函数
ES6 的箭头改变了常规函数的 this 运行时指向。
箭头函数的this,总是指向定义时所在的对象,而不是运行时所在的对象。
让我们改写上个示例的代码,使用箭头函数替换普通的函数声明:
/*
* 因为箭头函数的 this 总是指向定义时所在的对象,所以在这个示例中,this 都指向 Window 对象
*/
var func = () => {
console.log(this)
}
var obj1 = { msg : '1', obj: 'obj1' }
var obj2 = { msg : '2', obj: 'obj1' }
var obj3 = { msg : '3', obj: 'obj1' }
func() => Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, parent: Window, …}
func.call(obj1) => Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, parent: Window, …}
func.apply(obj2) => Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, parent: Window, …}
func.bind(obj3)() => Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, parent: Window, …}
总结
- 非箭头函数,this 总是指向调用他的对象
- 箭头函数,this 总是指向定义的对象