目录
1.代码输出结果
2.代码输出结果
3.代码输出结果
4.代码输出结果
5.代码输出结果
6.代码输出结果
7.代码输出结果
8.代码输出结果
9.代码输出结果
10.代码输出结果
11.代码输出结果
12.代码输出结果
13.代码输出结果
14.代码输出结果
总结
1.代码输出结果
function foo() {console.log( this.a );
}function doFoo() {foo();
}var obj = {a: 1,doFoo: doFoo
};var a = 2;
obj.doFoo()
输出结果为2,因为执行foo的是doFoo函数,函数默认执行window
但是如果doFoo函数里:
function doFoo() {// foo();console.log(this.a);//1}
输出的就是1,因为执行它的是obj对象,会隐式的把this指向obj对象
2.代码输出结果
var a = 10
var obj = {a: 20,say: () => {console.log(this.a)}
}
obj.say() //10 var anotherObj = { a: 30 }
obj.say.apply(anotherObj) //10
输出结果为10;10
apply或者bind通过绑定会指向里面的参数
但是这个是往外翻两层到window这层,所以都是最外层的a=10
如果换成普通函数的话就是20;30
3.代码输出结果
function a() {console.log(this);
}
a.call(null);
输出结果为window
call里面的参数如果是null或者undefined的话,this就会指向全局对象(浏览器里是window)
但是在严格模式情况下,参数是null输出的就是null;参数是undefined输出的是undefined
4.代码输出结果
var obj = { name: 'cuggz', fun: function(){ console.log(this.name); }
}
obj.fun() // cuggz
new obj.fun() // undefined
第二个new是取出了obj里的fun作为新的构造函数,所以里面没有name参数,结果为undefined
5.代码输出结果
var obj = {say: function() {var f1 = () => {console.log("1111", this);}f1();},pro: {getPro:() => {console.log(this);}}
}
var o = obj.say;
o();
obj.say();
obj.pro.getPro();
第一个:o=obj.say然后再调用o(),其实相当于是:
o=function() {var f1 = () => {console.log("1111", this);}f1();},
而且里面是箭头函数,翻第一层到f1,第二层到o,o是一个函数,它拥有this,与o平级的this就是window
第二个:obj.say() 翻第一层到f1,第二层到say,say平级的this就是obj
第三个:obj.pro.getPro()第一层翻到getPro,翻第二层到pro(注意对象是没有this 的!!只有函数有!),所以第二层直接翻到最外层,this就是window
对象不构成单独的作用域=>没有this
6.代码输出结果
var myObject = {foo: "bar",func: function() {var self = this;console.log(this.foo); console.log(self.foo); (function() {console.log(this.foo); console.log(self.foo); }());}
};
myObject.func();
func是myObject调用的,所以func里面的this是myObject,那么self也是
this.foo就是bar
self.foo也是bar
下面的函数被调用,里面作用域的this是func,所以它里面没有foo属性,输出undefined
然后最后一个self.foo,这块是一个闭包,里面函数可以调用外层函数的属性self.foo===bar
7.代码输出结果
window.number = 2;
var obj = {number: 3,db1: (function(){console.log(this);this.number *= 4;return function(){console.log(this);this.number *= 5;}})()
}
var db1 = obj.db1;
db1();
obj.db1();
console.log(obj.number); // 15
console.log(window.number); // 40
⚠️注意:obj.db1是个立即执行函数,它在obj对象定义完之后就会执行,然后返回后面的函数
所以在下面一系列调用函数之前就会有一次输出window,而且此时window上的number=8,在非严格模式下,自执行函数IIFE输出的this就是window
所以第一次先会输出一个window,此时这个函数变成了这样:
window.number = 2;
var obj = {number: 3,db1: function(){console.log(this);this.number *= 5;}
}
var db1 = obj.db1;
db1();
obj.db1();
console.log(obj.number); // 15
console.log(window.number); // 40
db1=obj.db1之后,db1如下:
db1=function(){console.log(this);this.number *= 5;}
打印这个this就是window(db1时函数不是对象),此时window . number=5*8=40
然后调用obj.db1(),this打印obj对象,obj.number=3*5=15
8.代码输出结果
var length = 10;
function fn() {console.log(this.length);
}var obj = {length: 5,method: function(fn) {fn();arguments[0]();}
};obj.method(fn, 1);
fn()这样调用只是一个普通函数,而不是作为对象的方法去调用,所以this是window,输出10
而arguments承接参数fn和1,但是这次相当于arguments(因为它是个类数组对象!)去调用方法,所以this指向arguments,而且它是伪数组有length,输出2
9.代码输出结果
var a = 1;
function printA(){console.log(this.a);
}
var obj={a:2,foo:printA,bar:function(){printA();}
}obj.foo(); // 2
obj.bar(); // 1
var foo = obj.foo;
foo(); // 1
obj.foo(),foo里的this指向obj;它跟上面的区别是:上面那个只是由obj穿参的,但是不是obj去调用的,只是函数进行到那里去调用了,不是对象调用的,而这个就是obj调用的,所以this是obj;
obj.bar(),现在printA函数就不是由obj对象调用而进行的了,所以printA函数里的this是全局对象,输出1;
var foo=obj.foo,那么foo相当于(foo是函数):
全局上的foo:printA,this是window,输出1
10.代码输出结果
var x = 3;
var y = 4;
var obj = {x: 1,y: 6,getX: function() {var x = 5;return function() {return this.x;}();},getY: function() {var y = 7;return this.y;}
}
console.log(obj.getX()) // 3
console.log(obj.getY()) // 6
第一个:又是一个立即执行函数,IIFE里面的this指向全局对象,所以x=3
第二个:调用对象是obj,this是obj的this,输出6
11.代码输出结果
var a = 10; var obt = { a: 20, fn: function(){ var a = 30; console.log(this.a)} }obt.fn(); // 20obt.fn.call(); // 10(obt.fn)(); // 20
obt.fn()调用者是obj,所以函数里的this是obj,输出obj的a,20
obt.fn.call(),call用来改变this,但是里面的参数为空(null),call里的参数为undefined或者null,this就是全局对象window,所以输出a为10
()的作用是改变运算顺序,所以这个跟第一个没什么区别,输出20
12.代码输出结果
function a(xx){this.x = xx;return this
};
var x = a(5);
var y = a(6);console.log(x.x) // undefined
console.log(y.x) // 6
x一开始相当于:
var x=function a(5){
this.x=5;
return this
}
没有对象调用这个函数,所以this.x说的是window.x=5,最后return this => window,返回的window又赋值回给var x了,所以最外层的window.x=window,x.x=undefined
顺序:
window.x=5
var x=window=>window.x=window
y一开始相当于:
var y=function a(6){
this.x=6;
return this
}
window上的x=6,返回window赋值给y
顺序:
window.x=6
window=y
输出y.x=6
13.代码输出结果
function foo(something){this.a = something
}var obj1 = {foo: foo
}var obj2 = {}obj1.foo(2);
console.log(obj1.a); // 2obj1.foo.call(obj2, 3);
console.log(obj2.a); // 3var bar = new obj1.foo(4)
console.log(obj1.a); // 2
console.log(bar.a); // 4
先是调用obj1.foo(2),obj1去调用的函数,所以obj1里的a是2,下面输出为2
然后obj1.foo.call(obj2,3),obj2上的a赋值为3
var bar=new obj1.foo(4)这是又new了一个,所以不会赋值之前的2,obj1上的a输出还是2
bar相当于:
var bar=function foo(){},注意new出来的比隐式绑定优先级高,所以里面的this是bar,bar的a就是4
14.代码输出结果
function foo(something){this.a = something
}var obj1 = {}var bar = foo.bind(obj1);
bar(2);
console.log(obj1.a); // 2var baz = new bar(3);
console.log(obj1.a); // 2
console.log(baz.a); // 3
这一步相当于:
var bar=function foo(sm){
this.a=sm;(this是obj1)
},obj1上
bar(2)=> obj1.a=2
var baz= new bar(3),new出来的比bind绑定的优先级高,所以this是baz,baz上的a为3
总结
改变this指向的四种方式:
函数默认指向,this是window
对象调用函数,函数里的this指向对象
显示绑定:call、apply、bind绑定,有参数绑定参数,null或者undefined就是window
通过new绑定this
其中new>显示>对象调用>默认指向
箭头函数里的this是一开始就定义好的,与后来谁去调用没有关系,this会继承自定义时的外层作用域,而且对象不会创建作用域,所以往外翻的时候只能翻到函数上
就比如这张图,obj.say()第一层到f1函数,第二层到say函数,然后找与say函数平级的this
obj.pro.getPro()第一层到getPro函数,第二层到最外层window
还有一些特殊情况比如立即执行匿名函数IIFE,在非严格模式下this就是window