前言
this指针和原型原型链一直是常问的知识点,会让你看这段代码说出执行结果,复习了一些知识后加以总结。本文主要复习this指针,还有一篇关于原型和原型链的文章,请移步。
以下所有内容都是个人理解,如有错误还请纠正。
一、默认的绑定规则
独立函数调用中的this指向全局对象,严格模式下声明的函数中,全局对象不可以作为this的默认绑定对象
// 全局
console.log(this===window); //true,,this和window之所以相等,是因为指向的是同一个引用
console.log({}==={}); //false,对象对比的是指针地址(引用)
// 函数的独立调用
function test(){
console.log(this===window) //true
}
test();
//立即执行函数
(function(){
console.log(this===window); //true
})();
二、隐式绑定规则
谁调用就指向谁(隐式丢失,参数赋值)是否有上下文对象(被某个对象拥有或包含),需注意函数调用另作引用时,this对象丢失的情况
var a=0;
var obj={
a:2,
foo:function(){
console.log(this); //obj,谁调用指向谁
function test(){// 特殊:闭包
// 定义:当函数执行的时候,导致函数被定义,并抛出
console.log(this); //window,函数的独立调用 obj.foo()()=test()
}
return test;
}
}
obj.foo();
obj.foo()();
var a=0;
function foo(a,b,c,d,e){
console.log(a,b,c,d,e) //undefined undefined undefined undefined undefined
console.log(this) //obj
}
var obj={
a:2,
foo:foo,
}
obj.foo();
1.隐式丢失
上面所说的都是obj.foo()直接调用,也可以将foo赋值给一个变量,这就是变量赋值情况,当前方法被重写或者赋值时,存在隐式丢失,此时this指向window。
// 1.隐式丢失,当前方法被重写或者赋值时(变量赋值情况)
var bar=obj.foo; //给了一个对象,但是没有执行,赋值后bar就只有当前foo的引用,就是一个函数
var bar=foo; //和上面一行完全一致
bar(); //window 函数独立调用
使用强绑定apply,bind,call
obj.foo(1,2,3,4,5);
bar.call(obj,1,2,3,4,5); //强绑定,第一个参数是绑定的对象,参数不定
bar.apply(obj,[1,2,3,4,5]); //参数确定,都放在数组
bar.bind(obj)(1,2,3,4,5);
// // 绑定失败
// bar.call(undefined,2,3,4,5); //失败就是window指向
// bar.apply(null,[2,3,4,5]);
2.参数赋值
var a=0;
function foo(){
console.log(this); //window 主要抓住函数怎么执行
}
function bar(fn){ //fn持有obj.foo引用
// console.log(this); //bar函数自己的this,暂时不考虑
// fn(); //独立调用,fn怎么调用,foo就怎么调用
//父函数可以决定子函数的this指向
// fn.call(obj); //上面打印的是obj
// fn(obj); //上面打印的是window
// new fn(); //上面打印的是foo{}
}
var obj={
a:2,
foo:foo,
}
bar(obj.foo);
高阶函数this指向
数组方法中的子函数this指向由父函数决定,在对应方法的api接口中指定了。
数组提供的内置接口,方法怎么写的,就决定this指向。
var arr=[1,2,3,4,5];
arr.forEach(function(item,idx,arr){ //当函数是参数的时候
console.log(this); //window
});
arr.sort(function(a,b){
console.log(this); //window
return a-b;
});
setInterval(function(){
console.log(this); //window
})
三、显示绑定规则
使用apply、call、bind对this对象进行强制绑定
var wang = {
name : "小王",
say : function(age,gender) {
console.log(this.name+age+gender);
}
}
var mary = {
name : "Mary",
}
wang.say(22,'male'); // 小王22male
wang.say.call(mary,21,'female'); // Mary21female
wang.say.apply(mary,[21,'female']); // Mary21female
wang.say.bind(mary,21,'female')(); // Mary21female
四、new绑定
使用构造函数new实例化对象时,this指向新声明的对象
function Person(){
this.a=1;
return this; //构造函数内部的this指向实例化后的对象person
// return的值为引用值会改变this指向
// return 1; //person
// return {}; // {}
}
var person=new Person();
console.log(person);