この点は、JavaScript では従来から比較的理解しにくいところであり、長年働いてきた人でも、ここの点がよくわからない場合があり、仕事でも面接でも、この点は比較的重要な知識ポイントです。
以下は、このポインティング ノートの詳細な調査であり、このポインティング ノートを理解して習得するのに役立つことを願っています。
このための拘束力のあるルール
このポイントを学ぶには、まずこの拘束力のあるルールを理解する必要があります
- デフォルトのバインディング
- 暗黙のバインディング
- バインディングを表示
- 新しいバインディング
- これが指している共通点
- アロー関数の this が指す
- ルール外のバインディング
バインディングルールを理解したら、コードを入力しましょう
デフォルトのバインディング
デフォルトのバインドは関数の独立呼び出しであり、独立呼び出しの関数 this はグローバルを指します. js 中国語ウィンドウでは、ノード内の空のオブジェクトです.
/**
* this的默认绑定(函数的独立调用)
*
*/
function foo() {
console.log(this) // window
}
foo()
暗黙のバインディング
暗黙のバインディングは、オブジェクト ポイント メソッドの形式を介してオブジェクト内のメソッドを呼び出すことであり、このメソッド内の this はこのオブジェクトを指します. オブジェクト内のメソッドがアロー関数の形式に置き換えられた場合、この内部がポイントします窓へ
/**
* this的隐式绑定(通过对象调用方法)
*
*/
const obj = {
name: 'lhq',
bar: function() {
console.log(this) // {name: 'lhq', bar: ƒ} // 控制台输出结果
}
}
obj.bar()
バインディングを表示
Display binding is through call(), apply(), bind(). これらのメソッドは、関数内の this ポイントを変更します
/**
* 显示绑定(通过call(), apply(), bind()),这些方法来改变this在函数中内部的指向
* 当call(),apply(), bind() 传入 null, undefined时,this指向window
*/
const obj1 = {
name: 'obj1',
foo: function() {
console.log(this.name)
}
}
const obj2 = {
name: 'obj2',
bar: function() {
console.log(this.name)
}
}
obj1.foo() // obj1
obj1.foo.call(obj2) // obj2
obj1.foo.apply(obj2) // obj2
const fn = obj1.foo.bind(obj2) // obj2
fn() // obj2
新しいバインド
新しいバインディングはオブジェクトをインスタンス化することです。これはこのオブジェクトを指します
/**
* new 绑定
* 通过new来调用构造函数,每次都会创建一个新的实例对象,且this指向这个对象
*/
function Person(name) {
this.name = name
this.student = function() {
console.log(this.name)
}
}
const person1 = new Person('lhq')
const person2 = new Person('hql')
person1.student() // lhq
person2.student() // hql
これが指している共通点
タイマー、イベントバインディング、配列内の高階関数のバインディング
/**
* 定时器
*
*/
setTimeout(() => {
console.log(this) // window
})
/**
* DOM的事件绑定
*
*/
const box = document.querySelector('.box')
box.addEventListener('click', function() {
console.log(this) // 指向的是被点击的DOM节点
})
/**
* 数组中高阶函数
* 高阶函数的定义: 一个函数接受一个函数作为参数或返回一个函数称为高阶函数
*/
const arr = [10, 20, 30, 40, 50]
arr.forEach(function(item) {
console.log(this) // window
})
アロー関数の this が指す
アロー関数は this をバインドせず、上位スコープの this を使用します。
アロー関数は this ポインターを内部的にバインドしないため、call()、apply()、bind() が内部の this ポインターを変更することは無効です。
let name = 'lhq'
const obj = {
name: 'hql',
bar: () => {
console.log(this.name) // lhq
}
}
これに縛られたインタビューの質問(回答付き)
最初の質問
/**
* 面试题: 1
*/
const name = 'window'
const person = {
name: 'person',
sayName: function() {
console.log(this.name)
}
}
function sayName() {
const sss = person.sayName
sss() // 函数的独立调用 window
person.sayName(); // this的隐式绑定 person
(person.sayName)(); // this的隐式绑定 person
(b = person.sayName)() // 函数的独立调用 window
}
sayName()
2つ目の質問
/**
* 面试题: 2
*/
var name = 'window'
const person1 = {
name: 'person1',
foo1: function() {
console.log(this.name)
},
foo2: () => console.log(this.name),
foo3: function() {
return function() {
console.log(this.name)
}
},
foo4: function() {
return () => {
console.log(this.name)
}
}
}
const person2 = {
name: 'person2'
}
person1.foo1() // person1 隐式绑定
person1.foo1.call(person2) // person2 (显示绑定优先级大于隐式绑定)
person1.foo2() // window (不绑定作用域,上层作用域是全局)
person1.foo2.call(person2) // window 箭头函数不受显示绑定的限制,往上层作用域查找
person1.foo3()() // window(独立函数调用)
person1.foo3.call(person2)() // window(独立函数调用)
person1.foo3().call(person2) // person2(最终调用返回函数式,使用的是显示绑定)
person1.foo4()() // person1
person1.foo4.call(person2)() // person2(上层作用域被显示的绑定了一个person2)
person1.foo4().call(person2) // person1(上层找到person1)
3つ目の質問
/**
* 面试题: 3
*
* 对象没有作用域
* 函数有作用域
*
* new 一个构造函数会创建一个空对象,
* 构造函数的this会指向这个空对象
* 往这个对象中加入属性和方法
* 最终返回这个对象 称为实例对象
*/
var name = 'window'
function Person(name) {
this.name = name
this.foo1 = function() {
console.log(this.name)
}
this.foo2 = () => console.log(this.name)
this.foo3 = function() {
return function() {
console.log(this.name)
}
}
this.foo4 = function() {
return () => {
console.log(this.name)
}
}
}
var person1 = new Person('person1')
var person2 = new Person('person2')
person1.foo1() // person1
person1.foo1.call(person2) // person2 显示绑定高于隐式绑定
person1.foo2() // person1 上层作用域找
person1.foo2.call(person2) // person1 箭头函数不受显示绑定影响
person1.foo3()() // window 函数的独立调用
person1.foo3.call(person2)() // window 函数的独立调用
person1.foo3().call(person2) // person2 使用显示绑定改变this的指向
person1.foo4()() // person1 箭头函数上层作用域查找
person1.foo4.call(person2)() // person2 通过显示绑定改变了foo4的this指向, 返回的是箭头函数 往上层作用域查找this 找到person2
person1.foo4().call(person2) // person1 // 箭头函数不受显示绑定约束
const obj = {
fun: function() {
// 这里的this指向obj 上层是全局
}
}
function foo() {
// 这里的this是foo
function bar() {
// 这里的this是bar
}
}
4つ目の質問
/**
* 面试题: 4
*
*/
var name = 'window'
function Person(name) {
this.name = name
this.obj = {
name: 'obj',
foo1: function() {
return function () {
console.log(this.name)
}
},
foo2: function() {
return () => {
console.log(this.name)
}
}
}
}
var person1 = new Person('person1')
var person2 = new Person('person2')
person1.obj.foo1()() // window 函数的独立调用
person1.obj.foo1.call(person2)() // window 函数的独立调用
person1.obj.foo1().call(person2) // person2 通过显示绑定改变函数内部的this指向
person1.obj.foo2()() // obj 调用返回了一个箭头函数,箭头函数再进行调用,因为箭头函数内部没有this,会往上层作用域找,找到obj
person1.obj.foo2.call(person2)() // person2 通过call调用foo2方法,并修改了它内部的this指向为perosn2,并返回一个箭头函数,再次执行这个箭头函数,箭头函数内部无this,往上层作用域找,又因为上层作用域的this指向被修改为person2,所以最终的打印结果为person2
person1.obj.foo2().call(person2) // obj
上記はすべての内容であり、完璧ではないかもしれません. 交換と修正を歓迎します.