Javascript中的this
本文总结于: 侯策《前端开发核心知识进阶》
this 到底指向谁
谁调用它,this 就指向谁。
更确切的说法:this 的指向,是在调用函数时根据执行上下文所动态确定的。
-
在函数体中,简单调用该函数时(非显式/隐式绑定下),严格模式下 this 绑定到 undefined,否则绑定到全局对象
window/global; -
一般构造函数 new 调用,绑定到新创建的对象上;
-
一般由 call/apply/bind
-
方法显式调用,绑定到指定参数的对象上; 一般由上下文对象调用,绑定在该对象上; 箭头函数中,根据外层上下文绑定的 this 决定 this指向。
全局环境下的this
function f1 () {
console.log(this)
}
function f2 () {
'use strict'
console.log(this)
}
f1() // window
f2() // undefined
上下文对象调用中的 this
const person = {
name: 'Lucas',
brother: {
name: 'Mike',
fn: function() {
return this.name
}
}
}
console.log(person.brother.fn())
//Mike
this 指向最后调用它的对象,因此输出将会是:Mike
bind/call/apply 改变 this 指向
const target = {}
fn.call(target, 'arg1', 'arg2')
const target = {}
fn.apply(target, ['arg1', 'arg2'])
const target = {}
fn.bind(target, 'arg1', 'arg2')()
构造函数和 this
new 操作符调用构造函数,具体做了什么?
- 创建一个新的对象;
- 将构造函数的 this 指向这个新对象;
- 为这个对象添加属性、方法等;
- 最终返回新对象。
var obj = {}
obj.__proto__ = Foo.prototype
Foo.call(obj)
如果构造函数中显式返回一个值,且返回的是一个对象,那么 this 就指向这个返回的对象;如果返回的不是一个对象,那么 this 仍然指向实例。
function Foo(){
this.user = "Lucas"
const o = {}
return o
}
const instance = new Foo()
console.log(instance.user)
//undefined
function Foo(){
this.user = "Lucas"
return 1
}
const instance = new Foo()
console.log(instance.user)
//Lucas
箭头函数中的 this 指向
箭头函数使用 this 不适用以上标准规则,而是根据外层(函数或者全局)上下文来决定。
const foo = {
fn: function () {
setTimeout(function() {
console.log(this)
})
}
}
console.log(foo.fn())
//windows
const foo = {
fn: function () {
setTimeout(() => {
console.log(this)
})
}
}
console.log(foo.fn())
// {fn: ƒ}
this 优先级相关
我们常常把通过 call、apply、bind、new 对 this 绑定的情况称为显式绑定;根据调用关系确定的 this 指向称为隐式绑定。
显示绑定优先级>隐示绑定优先级
new 的优先级 > bind的优先级
实现一个 bind 函数
Function.prototype.bind = Function.prototype.bind || function (context) {
var me = this;
var args = Array.prototype.slice.call(arguments, 1);
return function bound () {
var innerArgs = Array.prototype.slice.call(arguments);
var finalArgs = args.concat(innerArgs);
return me.apply(context, finalArgs);
}
}