小美是一个白富美,她想在代码美如画的程序员小金面前介绍自己——你好,我叫小美,我今年十八岁,上得厅堂下得厨房,能当爸也能当妈,会赚钱也很顾家。这样小金就被深深吸引,然后嫁入豪门......小红也是白富美,但是她是这样介绍自己的——小红,小红十八岁,小红会做饭,小红很会赚钱......小金听完就回答小红:你是一个好人,但是我们不适合......
同样是白富美,为何小金喜欢小美,因为小金的代码美如画,他熟练的运用this关键字。接下来,让我们一起学习this的指向问题。
一、this的使用场景
- 在全局中
在全局作用域中,this指向全局对象。在浏览器环境中,全局对象是window,Node.js中则是global。
- 在函数作用域中
函数中的this指向取决于函数的调用方式
1、函数的独立调用,触发的是默认绑定规则,该函数的this指向window/全局(global)。
2、函数被某个对象所拥有,或者函数被某个上下文对象调用时,触发隐式绑定规则,该函数中的this指向该上下文对象。
下面的情况有所不同,这是将函数调用返回的结果赋值给foo,然后访问对象的属性foo,此时foo并不是一个函数。在非严格模式下,this指向了全局
3、函数被多个对象链式调用时,this指向最近的那个对象(隐式丢失)
function foo(){
console.log(this.a);
}
var obj ={
a :1,
foo:foo
}
var obj2 ={
a :2,
obj:obj
}
obj2.obj.foo()
4、箭头函数:箭头函数不绑定自己的this
,它会捕获其所在上下文的this
值作为自己的this
值。这意味着在箭头函数中,this
的值是在定义函数时确定的,而非调用时。
var obj = {
a:1,
foo:function(){
//this
const fn =()=>{
console.log(this.a);
}
fn()
}}
obj.foo()
5、显示绑定: 通过call,apply,bind方法,将函数的this“强行掰弯”到一个对象中。
var obj ={
a:1
}
function foo(){
console.log(this.a);
}
foo.call(obj)
注: 下面代码是call方法的实现原理,感兴趣的小伙伴可以提前了解一下。
var obj ={
a:1
}
function foo(){
console.log(this.a);
}
Function.prototype.mycall = function(){
//拿到foo
//将foo引用到obj上
//让obj触发foo
//移除掉obj身上的foo
//arguments
const context = arguments[0]
const args = Array.from(arguments).slice(1) //[]
context.fn=this
context.fn()
const res = context.fn(...args)
delete context.fn
return res
}
let res =foo.mycall(obj,4,5)
console.log(res);
其内部的核心还是通过隐式绑定规则来实现的。
6、new绑定:this指向实例对象
function Person(){
//new的实现过程
// let obj ={
// name:'平平'
// }
// Person.call(obj)
// // obj_proto_ = Person.prototype
// return obj
this.name ='平平'
return 'hello'
}
let p = new Person() //{name:'平平'}
console.log(p.name);
如果你明白了new的实现过程,就很轻松的理解上面的绑定规则了