this关键字是JavaScript中最复杂的机制之一。它是一个很特别的关键字,被自动定义在所有函数作用域中。但是即便是经验丰富的JavaScript开发者也很难说清它到底指向什么:
任何足够先进的技术都和魔法无异。 ——Archur C.Clarke
误解
指向自身 :在函数中的this误解为指向函数本身;(每个函数的this是在函数调用时被绑定的,完全取决去函数的调用位置(也就是函数的调用方法,而不是函数声明的位置))
var count = 0; function foo(num) { console.log("foo: " + num); //尝试记录foo被调用的次数 this.count++; } foo.count = 0; for(var i = 0; i < 5; i++) { foo(i); } console.log(foo.count);//0 //如果没有在全局定义声明count并初始化,下面的会输出NaN console.log(count);//5 /* 上面的例子中函数foo中的this并不是指向函数本身,而是指向全局window对象,foo.count = 0为foo函数 初始化了count变量,但是this.count的自增是对于全局的count而言的,如果全局没有初始化或者没有声明count 的话,console.log(count)得到的结果就是NaN。 以上说明this并不是指向函数本身 */
它的作用域:误解this指向函数的作用域。(this任何时候都不指向函数作用域,作用域“对象“无法通过
JavaScript代码访问,因为它存在于JavaScript引擎内部。)function foo() { var a = 2; this.bar(); } function bar() { console.log(this.a); } foo(); /* foo函数中的this尝试调用全局的bar函数,这个是多余的一步, 因为bar函数就在全局中,可以通过作用域链访问到 然而bar函数中的this.a是指向全局window的,因为没有声明,所以返回undefined 上面的代码企图访问作用域,失败了 */
this的运用
纯粹的函数调用:全局函数的调用,this代表的是全局对象window
var foo = function() { console.log(this == window); } foo();//输出true //再次确认调用全局 var a = 1; function test() { this.a = 0; } console.log(a);//1 test(); console.log(a);//调用test()改变全局a之后输出0
作为对象的方法调用:作为某个对象的方法调用,this指向这个对象
var obj = { method: function() { console.log(this === obj);//true console.log(this === window)//false } } obj.method();
函数内调用内部函数:在函数内部调用函数,不管是在全局函数中调用函数,还是在方法中调用函数,this绑定全局window;也就是说子函数孙函数,只要是以函数的方式调用,this 就铁了心绑定 window 对象了
var foo = function() { console.log(this === window) var method = function() { console.log(this == window) } method(); } foo(); //两个输出都是true //在某个对象的方法中调用函数 var foo = { method: function() { console.log(this === foo); var methods = function() { console.log(window === this); } methods(); } } foo.method(); //两个都输出true
作为构造函数调用:所谓的构造函数,就是通过这个函数生成一个新的对象
function foo(name, age) { this.name = name; this.age = age; } var mewhat = new foo('mewhat','18'); console.log(mewhat); //输出foo {name: "mewhat", age: "18"},同时还有一个__proto__原型对象 //输出数据:{"name":"mewhat","age":"18"} console.log(JSON.stringify(mewhat)); //为了表明this不是全局对象,对代码做了点改变 var a = 2; function foo() { this.a = 1; } var test = new foo(); console.log(a);//2,全局中的a并没有被改变 console.log(test.a);//1
apply与call调用:apply()是函数对象的一个方法,它的作用是改变函数的调用对象,它的第一个参数就表示改变后的调用这个函数的对象,因此,this指的就是这第一个参数。call也是一样;apply与call的区别在于第二个参数,apply可以传递数组,而call只能是一个个数。
var x = 0; function test() { console.log(this.x); } var o = { x: 1, m: function() { console.log(this.x); } }; o.m.apply();
参考阮一峰dalao的博客Javascript的this用法
还有《你不知道的JavaScript 上卷》
坚持原创技术分享,您的支持将鼓励我继续创作!
微信打赏
支付宝打赏