前言:
this 总是指向一个对象, 而具体指向哪个对象是在运行时基于函数的执行环境动态绑定的, 而非函数被声明时的环境.
Part 1 作为对象的方法调用
当函数作为对象的方法被调用时, this 指向该对象, 如 obj.b(),this 指向 obj
- var obj = {
- name: "Sear",
- getName: function(){alert ( this === obj); // 输出: true
- return this.name ;
- } };
obj.getName();// 输出: Sear
我们说
当函数作为对象的方法被调用时, this 指向该对象
, 那么, 下面这种情况:
- var obj = {
- myName: "Sear",
- getName: function () {
- return this.myName;
- }
- };
obj.getName(); // 输出 Sear
var newObject = obj.getName;
console.log(newObject()) // 输出 undefine
诶? 怎么是 undefine 呢? 是这样的
当用另外一个变量 newObjec 来引用 obj.getName, 并且调用 getName2 时, 将就是下面 Part2 我们要提到的规律, 此时是普通函数调用方式, this 是指向全局 window 的, 所以程序的执行结果是 undefined.
Part 2 作为普通函数调用
当函数不作为对象的属性被调用时, 也就是我们常说的普通函数方式, 此时的 this 默认的, 指向全局变量 window. 在浏览器的 JavaScript 里, 这个全局对象是 window 对象
- window.name = "Hello"
- var obj = {
- name :"world",
- getName : function (){
- console.log(this === obj) // 输出 false
- console.log(this.name) // 输出 Hello
- return this.name
- }
- }
var get = obj.getName
get() // 输出 Hello
有时候我们会遇到一些困扰, 比如在 div 节点的事件函数内部, 有一个局部的 callback 方法, callback 被作为普通函数调用时, callback 内部的 this 指向了 window, 但我们往往是想让它指向 该 div 节点, 见如下代码: 参考javascript 设计模式与开发实践中的一个例子就很好理解了
- <html>
- <body>
- <div id="div1"> 我是一个 div</div> </body>
- <script>
- window.id = 'window';
- document.getElementById( 'div1' ).onclick = function(){ alert ( this.id ); // 输出:'div1'
- var callback = function(){
- alert ( this.id );
- callback();
- };
- </script>
- </html>
此时有一种简单的解决方案, 可以用一个变量保存 div 节点的引用:
document.getElementById( 'div1' ).onclick = function(){ var that = this; // 保存 div 的引
用
- var callback = function(){
- alert ( that.id ); // 输出:'div1' }
- callback();
- };
这种转换 this 的指向在小程序中也经常出现
Part 3 new 调用时指的是被构造的对象
- var obj = function (){
- this.name = 'Sear'
- }
var newObj = new obj()
newObj.name // 输出 Sear
但用 new 调用构造器时, 还要注意一个问题, 如果构造器显式地返回了一个 object 类型的对象, 那么此次运算结果最终会返回这个对象, 而不是我们之前期待的 this:
- var MyClass = function(){
- this.name = 'hello';
- return {
- // 显式地返回一个对象
- name: 'world'
- }
- };
- var obj = new MyClass();
obj.name // 输出: world
如果构造器显式地不是返回了一个 object 类型的对象, 那么不会造成上面的问题
- var MyClass = function(){
- this.name = 'hello'
- return 'world'; // 返回 string 类型
- };
- var obj = new MyClass();
obj.name; // 输出: hello
Part 4 call,apply 调用, 指向我们指定的对象, 即会改变 this 的指向
- window.name = "Hello"
- var obj = function() {
- return this.name
- }
- var obj1 = {
- name: 'world'
- }
- var obj2 = {
- name: 'Sear'
- }
obj(); // 输出 Hello
obj.call(obj1); // 输出 world
obj.apply(obj2); // 输出 Sear
参考书籍:
javascript 设计模式及开发实践
链接: https://pan.baidu.com/s/1Twpu1hM2YaPsNEqgiXsAZQ 密码: i8jf
仅限知识分享, 请勿商业使用, 谢谢
来源: http://www.jianshu.com/p/041c683f6031