这是我参与「第五届青训营 」笔记创作活动的第5天。
本堂课重点内容
本节课介绍了JS中的this.
详细知识点介绍
在学习React的过程中,我对this的使用产生了较大的疑惑,在查阅相关资料后遂就此文。
本文代码均在浏览器环境中执行。
首先,this会在函数运行时存在于函数的上下文中,进行动态绑定。
我们可以将this的绑定规则概括为下面四种:
- 默认绑定
- 隐式绑定
- 显式绑定
- new绑定
默认绑定
看函数调用时有无主体(与函数定义时情况无关)
// 默认绑定:独立函数调用
function foo(){
console.log(this)
}
foo() //window
这时this指向window
var obj = {
foo:function(){
conosle.log(this)
}
}
var test = obj.foo
test() //window
调用时函数没有调用主体,this同样指向window
function foo(){
function bar(){
console.log(this)
}
return bar
}
var fn = foo()
fn() // window
闭包的this同样指向window
隐式绑定
以.方式进行调用时,this指向.前的对象。
let obj = {
name:"LLLeo",
eat: function(){
console.log(this.name)
},
drink:function(){
console.log(obj.name)
}
}
obj.eat() // LLLeo
obj.drink() // LLLeo
object对象会被js引擎绑定到函数中的this里。
对于隐式绑定来说,必须在调用的对象内部存在一个对函数的引用。如果没有这样的引用,在调用时会报找不到该函数的错误。js引擎也正是通过这个引用实现了对this的绑定。
显式绑定
如果我们不希望在对象内部包含这个函数的引用,同时又希望在这个对象上进行强制调用,我们可以使用call和apply方法:
- 二者第一个参数都是为
this准备的对象 apply后面的参数为原函数的参数数组call后面的参数为原函数的参数列表- V8引擎对
apply进行了性能优化,更推荐使用
function foo(item1,item2){
console.log(this,item1,item2)
}
var obj = {
name:"obj"
}
foo.call(obj,[1,2]) // window 1 2
foo.apply(obj,1,2) // window 1 2
我们可以使用bind对函数进行强制绑定,减少不断.apply的重复。
function foo(item1,item2){
console.log(this,item1,item2)
}
var obj = {
name:"obj"
}
// 默认绑定于显式绑定冲突,显式绑定优先级更高
let newFoo = foo.bind(obj)
newFoo(1,2)
new绑定
我们可以使用new关键字将js中的函数当做一个类的构造函数来使用。
当使用new关键字来调用函数时:
- 创建一个全新的对象
- 这个新对象会执行prototype连接
- 这个新对象会绑定到函数调用的this上
- 如果函数没有返回其他对象,表达式会返回这个对象
function Person(name,age){
this.name = name;
this.age = age;
}
let person = new Person("LLLeo",21)
优先级规则
-
默认绑定的优先级最低
-
显式绑定优先级高于隐式绑定
function foo(){ console.log(this) } let obj = { foo: foo.bind("LLLeo"); } obj.foo() // LLLeo
- new绑定优先级高于隐式绑定
-
new绑定高于显式绑定
// new不能和apply/call一起使用 fuction foo(){ console.log(this) } let var = foo.bind("LLLeo") let obj = new var() // foo {}