在javascript中自己创建构造函数时可以利用this来指向新创建的对象上。这样就可以避免函数中的this指向全局了,如下
var x = 2; function test(){ this.x = 1; } var o = new test(); alert(x); //2
反之,如果不使用new,只把上面那个函数当做一个普通函数来使用的话,函数内部的this就会指向全局对象,如下
var x = 1; function test(){ this.x = 0; } test(); alert(x); //0
再之,如果把这个使用了this的函数放到一个对象当中,这个this会绑定到当前对象中,如下
var x=3; var point = { x : 0, y : 0, moveTo : function(x, y) { this.x = this.x + x; this.y = this.y + y; } }; point.moveTo(1, 1); alert(point.x);//1 alert(x);//3
综上看来,貌似function内部的this会找到最近的一个外层对象进行绑定,实在找不到对象就找window
然而,问题来了,如果是function内部的function使用this会怎样?如下:
var point = { x : 0, y : 0, moveTo : function(x, y) { // 内部函数 var moveX = function(x) { this.x = x;//this 绑定到了全局 }; // 内部函数 var moveY = function(y) { this.y = y;//this 绑定到了全局 }; moveX(x); moveY(y); } }; point.moveTo(1, 1); point.x; //==>0 point.y; //==>0 x; //==>1 y; //==>1
这样做this不仅没有找到外层对象point,反而直接找上了全局变量,导致凭空生成了两个全局变量,好危险的情况啊!!!
解决办法是有,就是在函数内部把this保存到一个局部变量中,如下
var point = { x : 0, y : 0, moveTo : function(x, y) { var that = this; // 内部函数 var moveX = function(x) { that.x = x; }; // 内部函数 var moveY = function(y) { that.y = y; } moveX(x); moveY(y); } }; point.moveTo(1, 1); point.x; //==>1 point.y; //==>1
所以说没两把刷子还真的不要随便去使用这个this,
后来接触到了es6,也就是俗称的下一代JavaScript,它给出了一个箭头函数“=>”.
看着箭头的简介和用法,貌似它就是一个function的简写嘛,反正看着特别不习惯,别扭!
比如说下面这个简单的箭头函数代码:
(a, b) => a + b
乍看,这是个表达式吧?哪里像个函数了,哪里像了?我这急性子,是谁吃饱了撑的想出这种简写的法子。。。
直到后来在介绍的最下面来了一句“箭头函数的 this 始终指向函数定义时的 this”,
也就是说,箭头函数里面的this再也不会变来变去了,即便是call和apply这两位也不能改变这个事实
var x = 1, o = { x : 10, test : () => this.x }; alert(o.x);//10 o.test(); // 1 o.test.call(o); // 依然是1
上面的结果很显然,this的指向确实没有任何变化,
但是,问题来了,不是说好的this会始终指向定义时的this吗,对象调用函数的方式中,this不是应该始终绑定在对象o上吗,输出的不是应该始终是10才对嘛???好晕!
实际原因是,箭头函数根本没有自己的this,导致内部的this就是外层代码块的this,这也是为什么箭头函数没有构造函数,不能使用new的原因!