this理解
this对象是在运行时基于函数的执行环境的定的。
用法
上下文
无论是否在严格模式下,在全局执行上下文中(在任何函数体外部)this 都指代全局对象。
1 2 3 4 5 6 7 8
| console.log(this === window); a = 37; console.log(window.a); this.b = "MDN"; console.log(window.b)
|
在全局上下文下调用函数,函数中的this,在严格模式下为全局对象,在非严格模式下为undefined。
1 2 3 4 5 6 7 8
| function f1(){ return this; } f1() === window; f1() === global;
|
函数作为对象的一个属性
如果函数作为对象的一个属性时,并且作为对象的一个属性被调用时,函数中的this指向该对象。
1 2 3 4 5 6 7 8 9
| var name = "The Window"; var object = { name: "My Object", getName: function() { return this.name; } } object.getName()
|
匿名函数的this略有不同,通常指向window。
1 2 3 4 5 6 7 8 9 10 11
| var name = "The Window"; var object = { name: "My Object", getNameFunc: function() { return function() { return this.name; } } } object.getNameFunc()();
|
匿名函数的在搜索活动对象this和arguments的时候会在作用域链上搜索,匿名函数外的执行环境为getNameFunc的执行环境getNameFunc的执行环境中的活动对象并没有this.name,就会停止搜索,直接将this指向window。
解决这种问题的方式是把this保存作为活动对象。
1 2 3 4 5 6 7 8 9 10 11 12
| var name = "The Window"; var object = { name: "My Object", getNameFunc: function() { var that = this; return function() { return this.name; } } } object.getNameFunc()();
|
函数用call或者apply调用
如果要想把 this 的值从一个上下文传到另一个,就要用 call 或者apply 方法。
1 2 3 4 5 6 7 8 9 10 11 12 13
| var obj = {a: 'Custom'}; var a = 'Global'; function whatsThis(arg) { return this.a; } whatsThis(); whatsThis.call(obj); whatsThis.apply(obj);
|
作为构造函数
通过new Foo()一个对象的方式调用构造函数,那么在函数中访问this的时候,this指向的是新对象。
1 2 3 4 5 6 7 8
| function Foo() { this.name = 'lucky4'; this.year = 1993; console.log(this); } var f1 = new Foo();
|
this指向新创造对象的原因是,在使用new操作符后,调用构造函数会经历一下4个步骤:
- 创建一个新对象。
- 将构造函数的作用域赋给新对象(因此this就指向了这个新对象)。
- 执行构造函数中的代码。
- 返回新对象。
1 2 3 4 5 6 7 8
| function Foo() { this.name = 'lucky4'; this.year = 1993; console.log(this); } Foo();
|
如果未通过new的方式访问构造函数,那么this将指向Window。
arrow function 中的this
在箭头函数中,this与封闭词法上下文的this保持一致。在全局代码中,它将被设置为全局对象。
1 2 3
| var globalObject = this; var foo = (() => this); console.log(foo() === globalObject);
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| var obj = { bar: function() { var x = (() => this); return x; } }; var fn = obj.bar(); console.log(fn() === obj); var fn2 = obj.bar; console.log(fn2()() == window);
|
JavaScript中的this与Java、C++中的this有什么区别?
首先看一段Java的代码:
1 2 3 4 5 6 7 8 9 10
| class Boolean { void peel(int i) { } } public class BananaPeel { public static void main(String[], args) { Banana a = new Banana(), b = new Banana(); a.peel(1); b.peel(2); } }
|
在执行代码的时候,编译器做了一些幕后工作,它把所操作对象的应用作为第一个参数传递给了peel(),上面的两个方法的调用变成了这样:
1 2
| Banana.peel(a, 1); Banana.peel(b, 2);
|
假设你希望在方法内部获得对当前对象的引用。由于上面引用是由编译器传入的,所以没有表示符可用,为此有个专门的关键字:this。this关键字只能在方法内部使用,表示对“调用方法的那个对象”的引用。
Java中this的用处有很多包括,返回对当前对象的引用,方便链式调用;将当前对象传递给其他方法;在一个构造器中调用另一个构造器等。
我认为Java的this和JavaScript的this主要有以下几个区别:
- this的值,Java中的this是一个引用,JavaScript中的this是一个类数组对象。
- Java中的this创建后不可改变,JavaScript中的this可以通过使用call,apply,bind等方式改变。也就是回到了对定义的理解Java中的this是编译时绑定的,而JavaScript中的this是基于运行时绑定的。
参考:
http://www.cnblogs.com/wangfupeng1988/p/3988422.html
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/this
《JavaScript高级程序设计》
《Java编程思想》