this指向是什么
函数在调用时,js会默认给this绑定一个值。 this的值只与调用方式和调用位置有关; this是在运行时被绑定的;
this的绑定规则
- 默认绑定 独立函数调用(函数没有被绑定在某个对象上进行调用)
- 隐式绑定 通过某个对象进行调用(调用位置是通过某个对象发起的)
- 显示绑定 隐式绑定需要在调用的对象内部有一个对函数的引用(比如属性),如果我们不希望在对象内部包含这个函数的引用,同时又希望在这个对象上进行强制调用,可以使用 apply、call、bind
- new绑定 js中函数可以当作一个类的构造函数来使用 使用new关键字调用的函数,会执行如下操作: 创建一个新的对象;新对象被执行prototype连接;新对象绑定到函数调用的this上;如果函数没有淡灰其他对象,表达式会返回这个新对象
function Person(name) {
console.log(this) //Person {}
this.name = name // Person {name: "why"}
}
var p = new Person("why")
console.log(p)
内置函数的绑定
当我们调用js的内置函数,或第三方库中的内置函数时,我们会传入另一个函数,js内部或第三方库会执行,这时候函数中的this需按经验判断
setTimeout —— window
forEach —— 数组中每一个对象;forEach第二个参数可以指定this绑定对象
div.onclick —— div
this规则之外
- 忽略显示绑定:如果显示绑定中,传入了null和undefined,那么显示绑定会被忽略,使用默认规则; 严格模式下this是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(); //window
- 间接函数引用:创建一个函数的间接引用,使用默认绑定规则
function foo() {
console.log(this)
}
var obj1 = {
name: "obj1",
foo: foo
}
var obj2 = {
name: "obj2"
}
obj1.foo(); //obj1
(obj2.foo = obj1.foo)(); //window
- ES6箭头函数this 箭头函数不使用this的四种标准,根据外层作用域决定this
this的规则优先级
- 默认规则优先级最低
- 显示高于隐式
- new高于隐式
- new高于bind
apply、call、bind
function.apply(thisArg, [argsArray])
function.call(thisArg, arg1, arg2, ...)
function.bind(thisArg, arg1, arg2, ...)
bind()方法创建新的绑定函数,绑定函数是一个怪异函数对象ECMAScript 2015。
调用时除第一个参数,其他将作为新函数的参数,也可以在调用时传参
面试题
var name = "window";
var person = {
name: "person",
sayName: function () {
console.log(this.name);
}
};
function sayName() {
var sss = person.sayName;
sss();
person.sayName();
(person.sayName)();
(b = person.sayName)();
}
sayName();
//window
//person
//person
//window
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.foo1.call(person2);
person1.foo2();
person1.foo2.call(person2);
person1.foo3()();
person1.foo3.call(person2)();
person1.foo3().call(person2);
person1.foo4()();
person1.foo4.call(person2)();
person1.foo4().call(person2);
//person1
//person2
//window
//window
//window
//window
//person2
//person1
//person2
//person1
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('ps1');
var person2 = new Person('ps2');
person1.foo1();
person1.foo1.call(person2);
person1.foo2();
person1.foo2.call(person2);
person1.foo3()();
person1.foo3.call(person2)();
person1.foo3().call(person2);
person1.foo4()();
person1.foo4.call(person2)();
person1.foo4().call(person2);
//ps1
//ps2
//ps1
//ps1
//window
//window
//ps2
//ps1
//ps2
//ps1
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('ps1');
var person2 = new Person('ps2');
person1.obj.foo1()();
person1.obj.foo1.call(person2)();
person1.obj.foo1().call(person2);
person1.obj.foo2()();
person1.obj.foo2.call(person2)();
person1.obj.foo2().call(person2);
//window
//window
//ps2
//obj
//ps2
//obj