JavaScript 内核第 1 / 7 章
this 绑定规则
从默认、隐式、显式到 new 绑定,按调用位置建立判断顺序。
this绑定规则(四种方式)
默认绑定,直接调用
❗ 提示
- 严格模式下,this默认绑定undefined
- 非严格模式下,this默认绑定globalThis 浏览器是 window
- 类中 默认开启严格模式 默认绑定和上层作用域的this不是一回事,直接调用函数时,没有显式绑定this的情况下,使用的this
隐式绑定
❗ 提示
被一个对象执行,调用,注意是被当作对象的一个方法来调用
const obj = {
name:'obj',
foo(){
console.log(this.name)
}
}
obj.foo() // this指向obj
function foo(){
console.log(this.length)
}
const arr = [foo,1,2]
arr[0]() // 这也会把this绑定到arr 即结果是 3
显示绑定
❗ 提示
bind/apply/call方式调用
- bind 函数只绑定,不执行,参数在绑定的时候可以传入,在调用的时候不能覆盖,会在后面添加新的参数
- call调用即执行,参数是单独传入
- apply调用即执行,参数通过数组传入
//三者调用
const obj ={ name:'this'}
var func = function(arg1, arg2) {};
// 直接调用了
func.call(obj, arg1, arg2);
func.apply(obj, [arg1, arg2]);
//返回一个函数
nfn = func.bind(obj,arg1)
nfn(arg2)
New 绑定
super调用会比较特殊
当一个函数以 super.method() 的形式被调用时,method 函数内的 this 与 super.method() 调用周围的 this 值相同,通常不等于 super 所指向的对象。这是因为 super.method 不是像上面的对象成员访问——它是一种特殊的语法,有不同的绑定规则。有关示例,请参见 super 参考。
🐵 提示
通过new 内部创建一个新的对象,绑定到this
绑定优先级
new绑定 > 显式绑定 > 隐式绑定 > 默认绑定
bind优先级高于apply/call
function Foo(){
console.log('this', this)
}
const objA ={
name:'objA',
}
const objB ={
name:'objB',
}
const fn = Foo.bind(objA)
fn.call(objB) // this { name: 'objA' }
new fn() // this Foo {}
const objC ={
name:'objC',
foo:fn
}
new objC.foo() // this Foo {}
特殊情况
非严格模式下,apply/call/bind绑定null/undefied时,这个绑定会被忽略,使用默认绑定(并不是降级,不会使用隐式绑定)
非严格模式下,基本类型会被转换成包装类型(对象),null和undefined会使用默认绑定
严格模式下,会直接使用绑定的类型,默认绑定是undefined
箭头函数
// 函数表达式
const fn1 = function(){}
// 用来改写 简化函数表达式
const fn2 = ()=> {}
const newArr = [1,2,3]
//1. 只有一个参数,可以把小括号省略
newArr.forEach(item=>{
console.log('item', item)
})
//2. 函数体只有一行代码,大括号可以省略(非return 语句)
newArr.forEach(item=>console.log('item', item))
//3. 如果函数体只有一行代码且是返回值,可以把return 也省略,默认返回
newArr.filter(item=>item>3)
//4. 如果默认返回是对象,那么需要给对象加上小括号
newArr.map(item=>({ num:item }))
规则:
- 箭头函数里没有绑定自己的this,如果在箭头函数使用了this,调用的时候会到上层作用域中查找this,就像普通变量查找一样的规则
- 没有arguments,可使用剩余参数来实现不定参数传递
const obj = {
name:'obj',
foo: function() {
const bar = ()=>{
console.log('this', this)
}
return bar
}
}
// 这里bar的this是上层作用域foo的this,如果改变foo的this指向,bar中的this也会跟着改变
const obj = {
name:'obj',
foo: ()=> {
const bar = ()=>{
console.log('this', this)
}
return bar
}
}
//如果把foo也改成了箭头函数,那么foo和bar的this指向都要继续往外查找,是全局作用域的this
// 注意!! 对象不是代码块,没有产生作用域!!
函数的调用方式:这里也是直接调用!!! 因为obj.foo()函数执行后,返回值是一个新的函数的地址!!!
obj.foo()()
也是通过小括号直接调用了
对象不是代码块,没有产生作用域!!