#Javascript:this用法整理
pingan 于 星期三, 18/12/2013 - 22:32 提交

常用Javascript的人都知道,[this这个关键字在一个函式内究竟指向谁]的这个问题很令人头大,本人在这裡整理了一下Javascript中this的指向的五种不同情况,其中前三种属于基本的情况,而后两种情况可基于前三种情况的方式来进行思考。

1.this指向于调用该函式之物件
如果你有学过C/C++,你可能会记得一个物件内的成员函式裡的this指的即是该成员函式所在之物件,但在Javascript裡则有那麽些许不同,Javascript裡的this看的是究竟是谁调用该函式,而不是看该函式被定义在哪个物件内,这个大原则抓到了,基本上就已经可以探知this的奥秘了。底下写一下这种情况的公式与范例:

公式

1 物件.函式(); //函式内的this指向该物件
范例

var obj = {
  x: 20,
  f: function(){ console.log(this.x); }
};

obj.f(); //由于调用f函式时,点前面物件为obj,故f内的this指向obj,则输出为20。

obj.innerobj = {
  x: 30,
  f: function(){ console.log(this.x); }
}

obj.innerobj.f(); //由于调用f函式时,点前面物件为obj.innerobj,故f内的this指向obj.innerobj,则输出为30。

2.this指向全域物件(浏览器:window物件、node.js:GLOBAL物件)
如果调用函式的前方并未有物件,则函式内this就指向全域物件。在浏览器内全域物件为window物件,而在node.js中全域物件则为GLOBAL物件。底下一样写一下这种情况的公式与范例:

公式

 函式(); //函式内的this指向全域物件
范例

var x = 10;
var f = function(){
  console.log(this.x);
};

f(); //由于调用f函式时,前方并未有[物件.]的形式,故f内的this指向全域物件,则输出全域变数的x(10)。
例外:在使用node.js时,若使用node file.js这样的方式执行js档,并不会让宣告的全域变数挂在全域物件上(意指会利用function将code整个包起来执行),故输出应为undefined。
前两种情况常见误导范例
范例一、物件之成员函式内有函式(感谢NSLin在实务读书会上的范例Code)
example1.js

var x = 10;
var obj = {
  x: 20,
  f: function(){
    console.log(this.x);
    var foo = function(){ console.log(this.x); }
    foo(); // (2)
  }
};

obj.f(); // (1)
这个范例会输出多少呢?别忘记大原则,在Javascript裡的this看的是究竟是谁调用该函式,故并不会输出20 20,而是输出20 10,为什麽呢?因为(1)obj.f()调用时,f前面物件为obj,故f内的this指向obj。但因为调用f内的(2)foo函式时是用foo(),调用的前方并未有物件,故foo内的this指向全域物件,所以输出会是全域变数的x的值。

若要让foo内使用obj.x的值,解法如下:

example1.js

var x = 10;
var obj = {
  x: 20,
  f: function(){
    console.log(this.x);
    var that = this; //使用that保留在这个函式内的this
    var foo = function(){ console.log(that.x); } //使用that取得obj
    foo();
  }
};

obj.f();
范例二、借用函式
example2.js

var x = 10;
var obj = {
  x: 20,
  f: function(){ console.log(this.x); }
};

obj.f(); // (1)

var fOut = obj.f;
fOut(); //(2)

var obj2 = {
  x: 30,
  f: obj.f
}

obj2.f(); // (3)
范例中三次调用之函式的this所指向的物件为何,不知道各位能不能看得出来。虽然用的是同一个函式,但是因为调用的不同,故this所指向的物件就不同。(1)obj.f()的f所指向的是obj,这比较没有问题,输出的会是20;而(2)fOut()裡的this,则是因为调用时前方无物件,则this所指的是全域物件,输出的会是10;最后(3)obj2.f()则是obj2去呼叫f,故f内的this指向的是obj2,输出的会是30。

3.this指向利用call或apply所指派给this的物件
有个方法可以更改前两种叙述中this指派的值,就是利用call与apply。call与apply都是呼叫该函式并让该函式的this指向给予call或apply的第一个参数。至于call和apply的差别则是在于其后面给予被调用之函式的参数放入的方法不同,一个是直接摊平放在第二个以后的参数;一个是直接放入一个裡面放要给予之参数的阵列。底下一样看一下公式和范例:

公式

(A物件.)函式.call(B物件,参数1,参数2,参数3, ......); //函式的this指向B物件(若B物件为null,则指向全域物件)
(A物件.)函式.apply(B物件,[参数1,参数2,参数3, ......]); //函式的this指向B物件(若B物件为null,则指向全域物件)
范例

var obj = {
  x: 20;
  f: function(){ console.log(this.x); }
};

var obj2 = {
  x: 30;
};

obj1.f.call(obj2); //利用call指派f的this为指向obj2,故输出为30
4.this指向new所产生之新物件
若将函式当作建构式(constructor)来用,则内部的this则指向于new所产生之新物件。

公式

new 建构式(); //建构式内之this指向new所产生之新物件
范例

function Monster(){
  this.hp = 100;
};

var monster = new Monster(); //Monster的this指向new出来之新物件并回传回来,new的写法就类似于下面的写法。
var monster = (function(){
  var _new = {

    constructor: Monster,

     __proto__: Monster.prototype

  }; //在IE内可能不相似
  _new.constructor(); //这也是为何说可以利用前三种情况来变化的原因,constructor呼叫时,this指向的即是_new这个物件。
  return _new;
})();
5.callback函式内的this会指向于调用放入该callback的函式之this所指向之物件
先想想在jQuery中,我们若要让#button这个元素被click的时候,内容改为“Clicked”这样的字串,该如何写呢?

clicked.js

$('#button').click(function(){
  this.html("Clicked");
})
此时这个this居然会指向$(‘#button’)这个物件,感觉很自然,但实际想想会觉得很神奇。假设你写一个function,它可以传入一个function,并在里面呼叫传入的function,你该怎么写呢?

function-to-function.js

var f = function(innerf){
  //前面的处理
  innerf(arg1, arg2, arg3, ......);
  //后面的处理
}
但如果这样写的话,innerf里的this根据前述规则就应该是全域物件了!那为什么常常别人实作的callback函式可让this指向于调用放入该callback的函式之this所指向之物件呢?这表示大家实际上会遵守一个规则,会将自己的this传给callback当作它的this来用!这也是为什麽我说这个情况其实也是前三种情况的变化而已了!所以上面的code应该改成如下的形式会比较好:

function-to-function-improved.js

var f = function(innerf){
  //前面的处理
  innerf.call(this, arg1, arg2, arg3, ......);
  //或是innerf.apply(this, [arg1, arg2, arg3, ......])
  //后面的处理
}

转载于:https://www.cnblogs.com/pingan1314/p/javascript_this.html

Javascript:this用法相关推荐

  1. JavaScript:switch用法

    JavaScript:switch用法 基本语法 switch(n){ case 1: 代码块1 break; 代码块2 语句: break; default: 代码块3 break; } 先定义一个 ...

  2. JavaScript setTimeout用法,js setTimeout带参数

    JavaScript setTimeout用法,js setTimeout带参数 ================================ ©Copyright 蕃薯耀 2021-07-07 ...

  3. javascript:void(0)和javascript:;的用法

    一.JavaScript:void(0) 我们经常会使用到 javascript:void(0) 这样的代码,那么在 JavaScript 中 javascript:void(0) 代表的是什么意思呢 ...

  4. Javascript Promise用法详解

    1.约定 本文的 demo 代码有些是伪代码,不可以直接执行. 没有特殊说明,本文所有 demo 都是基于 ES6 规范. Object.method 代表是静态方法, Object#method 代 ...

  5. javascript call用法及好处

    javascipt 中 Call的用法及好处 javascript call可以改变当前函数的作用域, 基本用法如下 function Person(name){this.name = name; } ...

  6. javascript opener 用法

    window.opener 的用法在一般的用法中,只是用来解决关闭窗口时不提示弹出窗口, 而对它更深层的了解一般比较少. 其 实 window.opener是指调用window.open方法的窗口. ...

  7. javascript this用法小结

    this是面向对象语言中的一个重要概念,在JAVA,C#等大型语言中,this固定指向运行时的当前对象.但是在javascript中,由于 javascript的动态性(解释执行,当然也有简单的预编译 ...

  8. Javascript typeof用法

    在js里用到数组,比如 多个名字相同的input, 若是动态生成的, 提交时就需要判断其是否是数组. if(document.mylist.length != "undefined" ...

  9. 55个javascript经典用法

    1. οncοntextmenu="window.event.returnValue=false" 将彻底屏蔽鼠标右键 <table border οncοntextmenu ...

  10. javascript 基本用法

    1.javascript简介*基于对象和事件驱动的语言,应用于客户端-基于对象提供了很多对象,可以直接拿过来使用-事件驱动html做网站静态效果,javascript能够呈现动态效果-客户端:专门指浏 ...

最新文章

  1. 对C语言程序进行编译时 针对以下情况,linux书上划的题的答案.doc
  2. Java黑皮书课后题第8章:**8.11(游戏:九个硬币的正反面)一个3*3的矩阵中放置了9个硬币,这些硬币有些面朝上有朝下。1表示正面0表示反面,每个状态使用一个二进制数表示。使用十进制数表示状态
  3. [译] Python 2.7.6 标准库——详见github
  4. python冒泡算法_python_冒泡算法
  5. STM32工作笔记003---认识了解RTOS系统
  6. cas5.3 使用http方式请求
  7. Java加载Class文件的原理机制
  8. 基于pytorch的transE代码详解
  9. 使用docker安装Jenkins教程
  10. JSONP解决前端跨域问题
  11. UI设计师必备|Web设计尺寸规范
  12. 日语---之百度百科
  13. android模拟电源按键
  14. 蓝牙协议栈测试,蓝牙协议栈认证:蓝牙BQB认证中End Product/Subsystem和Component的认证区别
  15. 内核与驱动文件的version magic匹配问题
  16. python x%y_Python运算符
  17. 二叉树的先序遍历(C++)
  18. adb删除软件_苹果免越狱如何安装ipa 苹果免越狱安装软件安装教程【详解】
  19. Zygote启动及其作用
  20. 安装pytorch 后torch.cuda.is_available()返回False的解决方法

热门文章

  1. [项目总结]在ios中使用soundtouch库实现变声
  2. 《Outlook时间整理术》一创建和使用自己的文件夹结构
  3. 使用ssh免密码登录Linux服务器
  4. 谈谈我对MVC的View层实现的理解
  5. SQLite3.8.4.2在Windows平台下的编译和使用
  6. 设计模式-Factory Method Pattern
  7. iphone-common-codes-ccteam源代码 CCTestMacros.m
  8. 10款优秀的跨平台免费生产力软件[转]
  9. 批处理文件总结(三)
  10. python数组替换_Python:替换数组中的值