携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第3天,点击查看活动详情
this的绑定规则总共有下面5种
1、默认绑定(严格/非严格模式) 2、隐式绑定 3、显式绑定 4、new绑定 5、箭头函数绑定
一.绑定规则
1.默认绑定
函数直接调用,一般发生在回调函数
- 独立函数调用:this指向全局对象
- 严格模式下,不能将全局对象用户默认绑定,this会指向undefined。在严格模式下调用函数则不受影响
- setTimeout比较特殊,严格模式和非严格模式下都是window
(1)非严格模式,this指向window
function foo() {
console.log(this) // window
}
// --------------------------------------
(2)运行在严格模式下,this会绑定到undefined
function foo() {
"use strict";
console.log( this.a );
console.log(this) // undefined
}
var a = 2;
// 调用
foo(); // TypeError: Cannot read property 'a' of undefined
// --------------------------------------
(3)严格模式下调用函数则不影响默认绑定
function foo() { // 运行
console.log( this.a );
}
var a = 2;
(function() { // 严格模式下调用函数则不影响默认绑定
"use strict";
foo(); // 2
})();
// --------------------------------------
(4)setTimeout
setTimeout(funtion(){
console.log(this) //window
})
2.隐式绑定
当函数引用有上下文对象时,隐式绑定规则会把函数中的this绑定到这个上下文对象。 简而言之:==谁调用this就指向谁==
function foo() {
console.log(this) //obj
console.log( this.a );
}
var obj = {
a: 2,
foo: foo
};
obj.foo(); // 2
隐式丢失 被隐式绑定的函数特定情况下会丢失绑定对象,应用默认绑定,把this绑定到全局对象或者undefined上。
// 虽然bar是obj.foo的一个引用,但是实际上,它引用的是foo函数本身。
// bar()是一个不带任何修饰的函数调用,应用默认绑定。
function foo() {
console.log( this.a );
}
var obj = {
a: 2,
foo: foo
};
var bar = obj.foo; // 函数别名
var a = "oops, global"; // a是全局对象的属性
bar(); // "oops, global"
参数传递就是一种隐式赋值,传入函数时也会被隐式赋值。 回调函数丢失this绑定是非常常见的。
function f1() {
console.log( this.a );
}
function f2(fn) {
// fn其实引用的是foo
fn(); // <-- 调用位置!
}
var obj = {
a: 2,
foo: f1
};
var a = "oops, global"; // a是全局对象的属性
f2( obj.foo ); // "oops, global"
3.显式绑定call,apply,bind
const obj1 = {
name:'wu',
getName(){
console.log(this)
console.log(this.name)
}
};
const obj2 = {
name:'jingjing'
}
obj1.getName.call(obj2)//obj2 jingjing
obj1.getName.apply(obj2)//obj2 jingjing
const fn = obj1.getName.bind(obj2)
fn() //obj2 jingjing
4.new绑定
使用new
来调用函数,或者说发生构造函数调用时,会自动执行下面的操作。
- 1、创建(或者说构造)一个新对象。
- 2、这个新对象会被执行[[Prototype]]连接。
- 3、这个新对象会绑定到函数调用的this。
- 4、如果函数没有返回其他对象,那么new表达式中的函数调用会自动返回这个新对象。
function fn(a){
this.a=a;
}
var bar = new fn(2)
console.log(bar.a) //2
<!-- this指向fn new出来的对象bar -->
5. ES6的箭头函数绑定
箭头函数比较特殊,箭头函数this为副作用域的this,不是调用的this,前四种方式的this都是动态
的,而==箭头函数的this指向是静态==的,声明的时候就确认下来了,比较符合js的此法作用域。(==父元素的this是什么,就是什么==)
window.name='wu'
const obj = {
name: 'jingjing',
age:'18',
getName()=>{
<!-- -->
console.log(this)//window
console.log(this.name)//wu
},
getAge:function(){
<!-- 通过obj.getAge调用,这里的this指向obj -->
setTimeout(()=>{
<!-- 所以这里的this也指向obj -->
console.log(this.age) //12
})
}
}
obj.getName();
obj.getAge();
二.优先级
箭头函数 -> new绑定 -> 显示绑定call/bind/apply -> 隐式绑定 -> 默认绑定