在我们日常开发和面试中,经常会遇到"this"指向的是谁,今天我们就聊一聊如何去判断this到底指向谁。
1.什么是this
它代表函数运行时,自动生成的一个内部对象,只能在函数内部使用。(emm.....不懂,算了还是直接敲代码吧)。
2.普通函数中的this指向
- 默认绑定
默认绑定,this指向window
var a = 1;
function fn(){
var a = 2;
console.log(this.a);
}
fn();//2
- 隐式绑定
function fn(){
console.log(this.a);
}
var obj2 = {
a:3,
fn:fn
}
obj2.fn();//3
var a = 2;
function fn(){
console.log(this.a);
}
var obj = {
a :1,
fn:fn
}
var foo = obj.fn;// 此时相当于默认绑定,this指向window
foo();//2
如果是链式对象引用,只有上层或者最后一层在调用作用中起作用。
function fn(){
console.log(this.a);
}
var obj2 = {
a:3,
fn:fn
}
var obj1 = {
a:2,
obj2:obj2
}
obj1.obj2.fn();//3
- 显示绑定:使用call或者apply、bind
var a = 1;
function fn(){
console.log(this.a);
}
var obj1 = {
a:2
}
fn.call(obj1);//2
显示绑定可以变种为硬绑定,后面就不能再修改this指向了
var a = 1;
function fn(){
console.log(this.a);
}
var obj1 = {
a:2
}
var bar = function(){
fn.call(obj1)
}
bar();//2
bar.call(window);//2
- new绑定
使用new调用fn时,我们会构造一个新对象并把它绑定到fn调用中的this上。
function foo(a){
this.a = a;
}
var bar = new foo(2);
console.log(bar.a);
3.箭头函数的this指向
var b = 2;
var obj = {
b:1,
fn1:()=>{
console.log(this.b);
}
}
obj.fn1();//2
不管在什么情况下,箭头函数this跟外层function的this是一致的,外层function指向谁,箭头函数的this就指向谁,如果外层不是function则指向window
var a = 3;
function foo(){
console.log(this);
var fn = ()=>{
console.log(this.a);
console.log(this);
}
fn();
}
var obj = {
a : 1,
foo:foo
}
obj.foo();
foo();
结果如下图:
![](https://img.haomeiwen.com/i8376922/f6f4929f9d2a04c8.png)
从上面例子,我们可以对this的指向总结几点:
1.函数直接调用,如上面例子fn(),this指向widow;
2.this指向是在函数执行的时候绑定的,而不是在函数创建的时候绑定的,所以是谁调用就指向谁;
3.匿名函数中,this指向一直指向window;
4.如果把null或者undefined作为this的绑定对象传入call/apply/bind,这些值在调用时会被忽略,实际应用的是默认绑定规则。
创建一个空对象最简单的办法是Object.creat(null),它和{}很像,但是并不会创建Object.prototype,它比{}更空
function foo(a,b){
console.log(a+b);
}
var Φ = Object.create(null);
foo.apply(Φ,[2,3]);
5.箭头函数里的this的指向是在函数创建的时候绑定的,无关乎谁调用。
最后说一下Object.create()的polyfill代码
function objectCreate(o){
function F(){};
F.prototype = o;
return new F();
}
我们首先创建一个函数F,然后通过.prototype属性使其指向我们想要关联的对象。最后再使用new F()来构造一个新对象来关联。
网友评论