this的绑定规则
绑定一:默认绑定;
独立函数调用
独立的函数调用我们可以理解成函数没有被绑定到某个对象上进行调用
独立函数的调用 指向全局对象window
绑定二:隐式绑定;
通过某个对象进行调用的 ,函数的this的绑定是函数调用的位置,而不是定义函数的位置
也就是它的调用位置中,是通过某个对象发起的函数调用。
隐式绑定: object.fn()–就是需要有对象主题来 调用起来 的函数 这个过程就叫做隐式绑定:
隐式绑定:就会自动将对象绑定到函数里面的this,指向调用者
绑定三:显示绑定;
隐式绑定有一个前提条件:
1.必须在调用的对象内部有一个对函数的引用(比如一个属性);
2. 如果没有这样的引用,在进行调用时,会报找不到该函数的错误;
3.正是通过这个引用,间接的将this绑定到了这个对象上;
call、apply、bind 我们明确的绑定了this指向的对象,所以称之为 显示绑定
call、apply第一个参数是相同的,后面的参数,apply为数组,call为参数列表;
如果我们希望一个函数总是显示的绑定到一个对象上
bind的绑定会形成一个新的函数 调用的时候新的函数,新函数就永远绑定的就是我们自己指定绑定的this对象了
标题绑定四:new绑定
JavaScript中的函数可以当做一个类的构造函数来使用,也就是使用new关键字
使用new关键字来调用函数是,会执行如下的操作:
1.创建一个全新的对象;
2.这个新对象会被执行prototype连接;
3.这个新对象会绑定到函数调用的this上(this的绑定在这个步骤完成);
4.如果函数没有返回其他对象,表达式会返回这个新对象;
标题this面试题一
var name = "window";
var person = {
name: "person",
sayName: function () {
console.log(this.name);
},
};
function sayName() {
var sss = person.sayName;
sss(); // window: 独立函数调用
person.sayName(); // person: 隐式调用
person.sayName(); // person: 隐式调用 (person.sayName)()其实相当于就是person.sayName();
(b = person.sayName)(); // window: 赋值表达式(独立函数调用)只要是赋值表达式--就是独立函数的调用---开发中不会写这种代码
}
sayName();
标题_this面试题二
var name = "window";
var 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);
};
},
};
var person2 = { name: "person2" };
// person1.foo1(); // person1(隐式绑定)
// person1.foo1.call(person2); // person2(显示绑定优先级大于隐式绑定)
// person1.foo2(); // window(箭头函数没有this,不绑定作用域,上层作用域是全局)
// person1.foo2.call(person2); // window
// person1.foo3()(); // window(独立函数调用)
// person1.foo3.call(person2)(); // window(独立函数调用)--重点是只看最终的this绑定是谁,这里是独立函数的调用
// person1.foo3().call(person2); // person2(最终调用返回函数式, 使用的是显示绑定)
// person1.foo4()(); // person1(箭头函数不绑定this, 上层作用域this是person1)
// person1.foo4.call(person2)(); // person2(上层作用域被显示的绑定了一个person2)
// person1.foo4().call(person2); // person1(上层找到person1)person1.foo4()使上层作用域变成person1,又因为箭头函数没有this,不绑定call,而是从上层作用域中找
标题_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);
};
});
}
// 函数每次new的时候都会创建一个新对象 每次的传入的this也是根据自己传入的参数自定义的this
var person1 = new Person("person1");
var person2 = new Person("person2");
person1.foo1(); // person1
person1.foo1.call(person2); // person2(显示高于隐式绑定)
person1.foo2(); // person1 (上层作用域中的this是person1)
person1.foo2.call(person2); // person1 (上层作用域中的this是person1)
person1.foo3()(); // window(独立函数调用)
person1.foo3.call(person2)(); // window
person1.foo3().call(person2); // person2
person1.foo4()(); // person1
person1.foo4.call(person2)(); // person2
person1.foo4().call(person2); // person1
var obj = {
name: "obj",
foo: function () {},
};
标题_this面试题四
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)是改变foo1的this指向为person2 但是foo1返回值为一个独立函数 独立函数的调用为window
person1.obj.foo1().call(person2); // person2 隐式绑定person2
person1.obj.foo2()(); // obj 上层作用域 主要看的返回值这个函数的上层作用域foo2是被谁调取的 这里是obj 调取的
person1.obj.foo2.call(person2)(); // person2 上层作用域 主要看的返回值这个函数的上层作用域foo2通过call改变this成为person2 所以是person2
person1.obj.foo2().call(person2); // obj 上层作用域是foo2通过隐式绑定变成obj, 箭头函数没有this 看上层作用域的指向
//
// 上层作用域的理解
// var obj = {
// name: "obj",
// foo: function() {
// 上层作用域是全局
// }
// }
// function Student() {
// this.foo = function() {
// 上层作用域是function Student
// }
// }