#Javascript:this用法整理
常用Javascript的人都知道,[this這個關鍵字在一個函式內究竟指向誰]的這個問題很令人頭大,本人在這裡整理了一下Javascript中this的指向的五種不同情況,其中前三種屬於基本的情況,而後兩種情況可基於前三種情況的方式來進行思考。
1.this指向於調用該函式之物件
如果你有學過C/C++,你可能會記得一個物件內的成員函式裡的this指的即是該成員函式所在之物件,但在Javascript裡則有那麼些許不同,Javascript裡的this看的是究竟是誰調用該函式,而不是看該函式被定義在哪個物件內,這個大原則抓到了,基本上就已經可以探知this的奧秘了。底下寫一下這種情況的公式與範例:
公式
1 |
物件.函式(); //函式內的this指向該物件 |
範例
1 |
var obj = {
|
2.this指向全域物件(瀏覽器:window物件、node.js:GLOBAL物件)
如果調用函式的前方並未有物件,則函式內this就指向全域物件。在瀏覽器內全域物件為window物件,而在node.js中全域物件則為GLOBAL物件。底下一樣寫一下這種情況的公式與範例:
公式
1 |
函式(); //函式內的this指向全域物件 |
範例
1 |
var x = 10; |
例外:在使用node.js時,若使用
node file.js這樣的方式執行js檔,並不會讓宣告的全域變數掛在全域物件上(意指會利用function將code整個包起來執行),故輸出應為undefined。
前兩種情況常見誤導範例
範例一、物件之成員函式內有函式(感謝NSLin在實務讀書會上的範例Code)
example1.js
1 |
var x = 10; |
這個範例會輸出多少呢?別忘記大原則,在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
1 |
var x = 10; |
範例二、借用函式
example2.js
1 |
var x = 10; |
範例中三次調用之函式的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的差別則是在於其後面給予被調用之函式的參數放入的方法不同,一個是直接攤平放在第二個以後的參數;一個是直接放入一個裡面放要給予之參數的陣列。底下一樣看一下公式和範例:
公式
1 |
(A物件.)函式.call(B物件,參數1,參數2,參數3, ......); //函式的this指向B物件(若B物件為null,則指向全域物件) |
範例
1 |
var obj = {
|
4.this指向new所產生之新物件
若將函式當作建構式(constructor)來用,則內部的this則指向於new所產生之新物件。
公式
1 |
new 建構式(); //建構式內之this指向new所產生之新物件 |
範例
1 |
function Monster(){
|
5.callback函式內的this會指向於調用放入該callback的函式之this所指向之物件
先想想在jQuery中,我們若要讓#button這個元素被click的時候,內容改為“Clicked”這樣的字串,該如何寫呢?
clicked.js
1 |
$('#button').click(function(){
|
此時這個this居然會指向$(‘#button’)這個物件,感覺很自然,但實際想想會覺得很神奇。假設你寫一個function,它可以吃一個function,並在裡面呼叫傳入的function,你該怎麼寫呢?
function-to-function.js
1 |
var f = function(innerf){
|
但如果這樣寫的話,innerf裡的this根據前述規則就應該是全域物件了!那為什麼常常別人實作的callback函式可讓this指向於調用放入該callback的函式之this所指向之物件呢?這表示大家實作上會遵守一個規則,會將自己的this傳給callback當作它的this來用!這也是為什麼我說這個情況其實也是前三種情況的變化而已了!所以上面的code應該改成如下的形式會比較好:
function-to-function-improved.js
1 |
var f = function(innerf){
|
參考資料
- Javascript的this用法:http://www.ruanyifeng.com/blog/2010/04/using_this_keyword_in_javascript.html
- [图解] 你不知道的 JavaScript - “this”:http://www.cnblogs.com/ruxpinsp1/archive/2008/04/20/1162463.html
#Javascript:this用法整理的更多相关文章
- JavaScript this用法总结(**************************************)
JavaScript this用法总结 在JavaScript中,this关键字可以说是最复杂的机制之一.对this的作用机制缺乏比较深入的理解很容易在实际开发中出现问题. 1.this的作用 为什么 ...
- Spring JdbcTemplate用法整理
Spring JdbcTemplate用法整理: xml: <?xml version="1.0" encoding="UTF-8"?> <b ...
- linq用法整理
linq用法整理 普通查询 var highScores = from student in students where student.ExamScores[exam] > score se ...
- linux学习:特殊符号,数学运算,图像与数组与部分终端命令用法整理
指令:let.expr.array.convert.tput.date.read.md5.ln.apt.系统信息 一:特殊符号用法整理 系统变量 $# 是传给脚本的参数个数 $0 是脚本本身的名字 $ ...
- #ifndef#define#endif的用法(整理)
[转] #ifndef#define#endif的用法(整理) 原作者:icwk 文件中的#ifndef 头件的中的#ifndef,这是一个很关键的东西.比如你有两个C文件,这两个C文件都in ...
- Javascript Array 方法整理
Javascript Array 方法整理 Javascript 数组相关方法 说明 大多数其它编程语言不允许改变数组大小,越界访问索引会报错,但是 javascript不会报错,不过不建议直接修改a ...
- Google Guava 库用法整理<转>
参考: http://codemunchies.com/2009/10/beautiful-code-with-google-collections-guava-and-static-imports- ...
- MySQL中使用SHOW PROFILE命令分析性能的用法整理(配合explain效果更好,可以作为优化周期性检查)
这篇文章主要介绍了MySQL中使用show profile命令分析性能的用法整理,show profiles是数据库性能优化的常用命令,需要的朋友可以参考下 show profile是由Jerem ...
- 《JavaScript实用效果整理》系列分享专栏
整理一些使用的JavaScript效果,在Web开发中遇到的比较好的动态效果,都收藏在这里,对以后的网站开发增加不少的色彩 <JavaScript实用效果整理>已整理成PDF文档,点击可直 ...
- Android spannableStringBuilder用法整理
Android spannableStringBuilder用法整理 分类: Android开发2013-11-29 10:58 5009人阅读 评论(0) 收藏 举报 Androidspannabl ...
随机推荐
- Linux各发行版本简介
简介 Linux 主要作为Linux发行版(通常被称为"distro")的一部分而使用.这些发行版由个人,松散组织的团队,以及商业机构和志愿者组织编写.它们通常包括了其他的系统软件 ...
- 关于C指针
地址概念:内存基本单元是一个字节,一个字节8个位.在定义变量的时候,如int a=10:系统为变量a分配2个字节空间:1000~1001,并在1001~1002中存有数据10.内存中没有变量a,只有1 ...
- C#大纲
输入输出--数据类型--变量与常量--运算符表达式--语句(顺序.分支.循环)--数组--函数--结构体一.输入与输出.Console.ReadLine();Console.WriteLine();C ...
- Visual Studio安装项目中将用户选择的安装路径写入注册表的方法[转]
在你的工程名上右击 -> View ->Registry(视图 -> 注册表) 在你需要写注册表的主键下,例如我注册firefox插件的例子是: (1)右击HKEY_CURRENT_ ...
- jquery选择器 :first与:first-child区别
一个例子: <ul> <li>John</li> <li>Karl</li> <li>Brandon</li> ...
- D django 用户认证系统
django认证系统包含三个部分:用户.权限和分组 安装 django项目默认启用了认证系统,如果不是使用django-admin.py创建项目的可以通过在settings配置文件里面的INSTALL ...
- [JAVA设计模式]第三部分:结构模式
声明:原创作品,转载时请注明文章来自SAP师太技术博客( 博/客/园www.cnblogs.com):www.cnblogs.com/jiangzhengjun,并以超链接形式标明文章原始出处,否则将 ...
- Github上不错的Android开源代码(一)
总有一些朋友很热心的整理一些好的资料,在收集之后,可以用作阅读.学习和实践.小伙伴们,总有一天,你也能写出 Niubility 的 Android App :-) 为了防止以上链接失效,以及部分内容丢 ...
- iOS - File Archive/UnArchive 文件压缩/解压
1.ZipArchive 方式 ZipArchive 只能对 zip 类文件进行压缩和解压缩 GitHub 网址:https://github.com/ZipArchive/ZipArchive Zi ...
- 用Maven创建第一个项目
1.在Eclipse左侧的空白处点击鼠标右键,选择:New>Other : 2.选择Maven项目,点击"Next"按钮: 3.保持默认,直接点击“Next”按钮: 4.选择 ...