this的绑定规则有几种?
- 默认绑定
-
当函数独立调用时
-
this 绑定到全局对象
- 在浏览器环境中为 window,Node.js 环境中为 global
- 在严格模式,则默认绑定为 undefined。
-
案例代码
function myFunction() { console.log(this); } myFunction(); // this 指向 window(浏览器中)或 global(Node.js 环境中)
-
- 隐式绑定
-
当函数作为对象的方法调用时,this 绑定到该对象。
-
案例代码
const myObject = { name: 'Alice', sayName() { console.log(this.name); } }; myObject.sayName(); // this 指向 myObject,输出 "Alice"
-
- 显式绑定
-
明确this指向的对象,第一个参数相同并要求传一个对象。
-
apply/call
-
bind
-
案例代码
-
function sayHello() {
console.log(`Hello, ${this.name}!`);
}
const person = { name: 'Alice' };
sayHello.call(person); // this 指向 person,输出 "Hello, Alice!"
- new绑定:
-
当构造函数被 new 关键字调用时,this 绑定到新创建的对象实例。
-
创建一个全新对象
-
新对象被执行prototype链接
-
新对象绑定到函数调用的this
-
如果函数没有返回其他对象,表达式会返回这个对象
-
-
案例代码
function Person(name) { this.name = name; } const alice = new Person('Alice'); console.log(alice.name); // 输出 "Alice"
-
- 箭头函数绑定
- 箭头函数没有自己的 this 值
- 箭头函数中的 this 值指向最近的非箭头函数的 this 值(来自于函数作用域链)
- 如果没有这样的函数的情况下指向全局对象
this绑定优先级
- 默认绑定<隐式绑定<显示绑定<new绑定
- new绑定不可与call/apply一起使用
- new可以和bind一起使用,new绑定优先级更高
绑定之外的情况
- 在显示绑定中,我们传入一个
null
或者undefined
- 那么这个显示绑定会被忽略,使用默认规则
function foo(){
console.log(this);
}
var obj = {
name:"why"
}
foo.call(obj) //obj对象
foo.call(null) //window
foo.call(undefined) //window
var bar = foo.bind(null);
bar()
- 创建一个函数的间接引用,这种情况使用默认绑定规则
-
赋值(obj2.foo = obj1.foo)的结果是foo函数;
-
foo函数被直接调用,那么是默认绑定;
function foo() { console.log(this); } var obj1 = { name: "obj1", bar: foo } var obj2 = { name: "obj2" } obj1.bar(); //obj1对象 (obj2.bar = obj1.bar)() //window
-
如何使用call()和apply()方法改变this的值?
-
call()和apply()的区别
call()
方法接受一个参数列表apply()
方法接受一个数组参数。
function foo(){} foo.call(this,1,2,3) foo.apply(this,[1,2,3]) const foo1 = foo.bind(this,1,2) foo1(3)
如何使用bind()方法改变this的值?
-
bind() 方法创建一个新的函数
- 该函数与原始函数相同
- 但 this 值被绑定到指定的对象。
-
bind() 方法接受一个参数,即要绑定到函数 this 的对象。
let obj1 = { name: "Bob" }; function sayHello() { console.log(`Hello, my name is ${this.name}.`); } let sayHelloToBob = sayHello.bind(obj1); sayHelloToBob(); // 输出 "Hello, my name is Bob."
在 setTimeout() 或 setInterval() 中,this 的值是什么?
-
在 setTimeout() 或 setInterval() 中,this 的值取决于外部作用域
const obj = { foo1: function () { return setTimeout(() => { console.log(this); // obj对象 }, 100) }, foo2: () => { return setTimeout(() => { console.log(this); // window }, 100) }, foo3: function () { return setTimeout(function () { console.log(this); // obj2对象 }.bind(obj2), 100) } } const obj2 = { name: "obj2" }
如何理解this关键字的动态绑定特性?
- 普通函数this的值在运行时动态地确定,而不是在编译时确定。
- 具体来说,this 的值取决于函数的调用方式,而不是函数本身的定义方式。
- 注意:
- 在使用箭头函数或 bind() 方法时
- this 的值不会动态绑定,而是在创建函数时确定,因此会受到外层作用域的影响。
- 在使用箭头函数或 bind() 方法时
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
person2.foo2() //person2
person2.foo2.call(person2) //person2
person1.foo3()() //window
person1.foo3.call(person2)()//window
person1.foo3().call(person2)//person2
person1.foo4()() // window
person1.foo4.call(person2)() //person2
person1.foo4().call(person2) //window