理解this的指向

一、理解this绑定

  1. 函数在调用时,JavaScript会默认给函数绑定一个this
  2. this的绑定和定义的位置(编写的位置)无关
  3. this的绑定和调用方式以及调用的位置有关
  4. this是在运行时绑定的
  5. 优先级:new > bind > apply/call > 隐式绑定 > 默认绑定

二、this的绑定规则

  1. 默认绑定
// 具名函数调用
fucniton foo(){
    
    
  console.log('foo',this)  
}
foo() // this指向window
// 匿名函数调用
// const foo = function(){
    
    
//   console.log('foo', this)
// }
// foo() // this指向window
  1. 隐式绑定
// 隐式绑定
const info = {
    
    
    name: '张三',
    age: 24,
    sayName() {
    
    
        console.log('this指向', this)
    }
}
info.sayName() // this指向 {name: '张三', age: 24, sayName: ƒ}
  1. 显示绑定
function foo(name,age) {
    
    
    console.log('参数', name, age)
    console.log('foo被调用时this的指向', this)
}
// apply
// 第一个参数:绑定this
// 第二个参数:已数组形式的实参

// foo.apply('apply', ['张三', 24])
// 参数 张三 24
// this的指向.js:20 foo被调用时this的指向 String {'apply'}

// call
// 第一个参数:绑定this
// 第二个参数:以逗号隔开的参数序列

// foo.call('call', '张三', 24)
// 参数 张三 24
// foo被调用时this的指向 String {'call'}

// bind
// 第一个参数:绑定this
// 第二个参数:以逗号隔开的参数序列
// const changethis = foo.bind('bind', '张佳佳', 24)
// changethis()
// 参数 张佳佳 24
// foo被调用时this的指向 String {'bind'}

// 显示绑定的特殊情况 当apply、call、bind第一个参数为null或者undefined时,this指向window
function foo() {
    
    
    console.log('this', this)
}
// const bindFoo = foo.bind(null)
// bindFoo() // this Window {window: Window, self: Window, document: document, name: '', location: Location, …}
// const bindFoo = foo.bind(undefined)
// bindFoo() // this Window {window: Window, self: Window, document: document, name: '', location: Location, …}

foo.apply(null) // this Window {window: Window, self: Window, document: document, name: '', location: Location, …}
foo.apply(undefined) // this Window {window: Window, self: Window, document: document, name: '', location: Location, …}

foo.call(null) // this Window {window: Window, self: Window, document: document, name: '', location: Location, …}
foo.call(undefined) // this Window {window: Window, self: Window, document: document, name: '', location: Location, …}
  1. 内置函数this绑定
setTimeout(() => {
    
    
    console.log('settimeout', this) // this指向window
}, 1000);

const btn = document.querySelector("#btn")
btn.onclick = function() {
    
    
    console.log('onclick', this) // this指向btn元素
}

btn.addEventListener('click', function() {
    
    
    console.log('addEventListener', this) // this指向btn元素
})
['abc', 'cba'].forEach(element => {
    
    
    console.log('forEach', this) // this指向window
});

5、new绑定this

function Foo () {
    
    
    this.name = 'zjj'
    this.age = 24
    console.log(this) // Foo {name: 'zjj', age: 24}
}
const foo = new Foo()
console.log(foo) // Foo {name: 'zjj', age: 24}

三、this绑定优先级

1、默认绑定的优先级最低
2、显示绑定高于隐式绑定

function foo() {
    
    
    console.log('this指向', this)
}
const info = {
    
    
    name: '张三',
    age: 24,
    foo
}
const obj = {
    
     name: '显示绑定' }
info.foo.apply(obj) // this指向 {name: 'apply显示绑定'}
info.foo.call(obj) // this指向 {name: 'call显示绑定'}
const newFun = info.foo.bind(obj)
newFun() // this指向 {name: 'bind显示绑定'}


3、new绑定高于隐式绑定

  • new 操作符做了什么?
  • 在内存中创建一个新对象。
  • 这个新对象内部的[[Prototype]]特性被赋值为构造函数的prototype 属性。
  • 构造函数内部的 this 被赋值为这个新对象(即 this 指向新对象)。
  • 执行构造函数内部的代码(给新对象添加属性)。
  • 如果构造函数返回非空对象,则返回该对象;否则,返回刚创建的新对象。

4、new绑定高于bind显示绑定

  • new绑定不能和apply和call一起使用所以不存在谁的优先级高的问题
  • new绑定高于bind显式绑定
function foo() {
    
    
    console.log('this指向', this)
}
const obj = {
    
    
    name: '张三'
}
const bindFun = foo.bind(obj)
bindFun() // this指向 {name: '张三'}
new bindFun() // this指向 foo {}

5、bind绑定优先级高于apply和call

// bind和apply/call的优先级
function foo() {
    
    
    console.log('this', this)
}
const obj = {
    
     name: '张三' }
const bindFoo = foo.bind(obj)
bindFoo() //this {name: '张三'}
bindFoo.apply('apply') // this {name: '张三'}
bindFoo.call('call') // this {name: '张三'}

猜你喜欢

转载自blog.csdn.net/Z_J_CSDN/article/details/125610433