前端里的this指向问题
- 游戏开发
- 2025-09-07 20:36:02

目录
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); // 40db1=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(); // 1obj.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(); // 20 obt.fn.call(); // 10 (obt.fn)(); // 20obt.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) // 6x一开始相当于:
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); // 2 obj1.foo.call(obj2, 3); console.log(obj2.a); // 3 var 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); // 2 var 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
前端里的this指向问题由讯客互联游戏开发栏目发布,感谢您对讯客互联的认可,以及对我们原创作品以及文章的青睐,非常欢迎各位朋友分享到个人网站或者朋友圈,但转载请说明文章出处“前端里的this指向问题”