JavaScript this调用规则说明


Posted in Javascript onMarch 08, 2010

JavaScript函数调用规则一
(1)全局函数调用:

function makeArray( arg1, arg2 ){ 
return [this , arg1 , arg2 ]; 
}

这是一个最常用的定义函数方式。相信学习JavaScript的人对它的调用并不陌生。
调用代码如下:
makeArray('one', 'two');
// => [ window, 'one', 'two' ]
这种方式可以说是全局的函数调用。
为什么说是全局的函数?
因为它是全局对象window 的一个方法,
我们可以用如下方法验证:
alert( typeof window.methodThatDoesntExist );
// => undefined
alert( typeof window.makeArray);
// => function
所以我们之前调用 makeArray的方法是和下面调用的方法一样的
window.makeArray('one', 'two');
// => [ window, 'one', 'two' ]
JavaScript函数调用规则二
(1)对象方法调用:
//creating the object 
var arrayMaker = { 
someProperty: 'some value here', 
make: makeArray 
}; 
arrayMaker.make('one', 'two'); // => [ arrayMaker, 'one', 'two' ] 
//或者用下面的方法调用: 
arrayMaker['make']('one', 'two'); // => [ arrayMaker, 'one', 'two' ]

看到这里跟刚才的区别了吧,this的值变成了对象本身.
你可能会质疑:为什么原始的函数定义并没有改变,而this却变化了呢?
非常好,有质疑是正确的。这里涉及到 函数在JavaScript中传递的方式,
函数在JavaScript 里是一个标准的数据类型,
确切的说是一个对象.你可以传递它们或者复制他们.
就好像整个函数连带参数列表和函数体都被复制,
且被分配给了 arrayMaker 里的属性 make,那就好像这样定义一个 arrayMaker :
var arrayMaker = { 
someProperty: 'some value here', 
make: function (arg1, arg2) { 
return [ this, arg1, arg2 ]; 
} 
};

如果不把调用规则二 弄明白,那么在事件处理代码中 经常会遇到各种各样的bug,举个例子:
<input type="button" value="Button 1" id="btn1" /> 
<input type="button" value="Button 2" id="btn2" /> 
<input type="button" value="Button 3" id="btn3" onclick="buttonClicked();"/> 
< script type="text/javascript"> 
function buttonClicked(){ 
var text = (this === window) ? 'window' : this.id; 
alert( text ); 
} 
var button1 = document.getElementById('btn1'); 
var button2 = document.getElementById('btn2'); 
button1.onclick = buttonClicked; 
button2.onclick = function(){ 
buttonClicked(); 
}; 
< /script>

点击第一个按钮将会显示”btn1”,因为它是一个方法调用,this为所属的对象(按钮元素) 。
点击第二个按钮将显示”window”,因为 buttonClicked 是被直接调用的( 不像 obj.buttonClicked() ),
这和第三个按钮,将事件处理函数直接放在标签里是一样的.所以点击第三个按钮的结果是和第二个一样的。
所以请大家注意:
button1.onclick = buttonClicked; 
button2.onclick = function(){ 
buttonClicked(); 
};

this指向是有区别的。
JavaScript函数调用规则三
当然,如果使用的是jQuery库,那么你不必考虑这么多,它会帮助重写this的值以保证它包含了当前事件源元素的引用。
//使用jQuery 
$('#btn1').click( function() { 
alert( this.id ); // jQuery ensures 'this' will be the button 
});

那么jQuery是如何重载this的值的呢?
答案是: call()和apply();
当函数使用的越来越多时,你会发现你需要的this 并不在相同的上下文里,这样导致通讯起来异常困难。
在Javascript中函数也是对象,函数对象包含一些预定义的方法,其中有两个便是apply()和call(),我们可以使用它们来对 this进行上下文重置。
<input type="button" value="Button 1" id="btn1" /> 
<input type="button" value="Button 2" id="btn2" /> 
<input type="button" value="Button 3" id="btn3" onclick="buttonClicked();"/> 
< script type="text/javascript"> 
function buttonClicked(){ 
var text = (this === window) ? 'window' : this.id; 
alert( text ); 
} 
var button1 = document.getElementById('btn1'); 
var button2 = document.getElementById('btn2'); 
button1.onclick = buttonClicked; 
button2.onclick = function(){ 
buttonClicked.call(this); // btn2 
}; 
< /script>

JavaScript函数调用规则四
(1)构造器
我不想深入研究在Javascript中类型的定义,但是在此刻我们需要知道在Javascript中没有类,
而且任何一个自定义的类型需要一个初始化函数,使用原型对象(作为初始化函数的一个属性)定义你的类型也是一个不错的想法,
让我们来创建一个简单的类型
//声明一个构造器 
function ArrayMaker(arg1, arg2) { 
this.someProperty = 'whatever'; 
this.theArray = [ this, arg1, arg2 ]; 
} 
// 声明实例化方法 
ArrayMaker.prototype = { 
someMethod: function () { 
alert( 'someMethod called'); 
}, 
getArray: function () { 
return this.theArray; 
} 
}; 
var am = new ArrayMaker( 'one', 'two' ); 
var other = new ArrayMaker( 'first', 'second' ); 
am.getArray(); 
// => [ am, 'one' , 'two' ] 
other.getArray(); 
// => [ other, 'first', 'second' ]

一个非常重要并值得注意的是出现在函数调用前面的new运算符,没有那个,你的函数就像全局函数一样,且我们创建的那些属性都将是创建在全局对象上(window),而你并不想那样。
另外一点,因为在你的构造器里没有返回值,所以如果你忘记使用new运算符,将导致你的一些变量被赋值为 undefined。
所以构造器函数以大写字母开头是一个好的习惯,这可以作为一个提醒,让你在调用的时候不要忘记前面的new运算符.
这样 初始化函数里的代码和你在其他语言里写的初始化函数是相似的.this的值将是你将创建的对象.
总结
我希望通过这些来使你们理解各种函数调用方式的不同,
让你的JavaScript代码远离bugs。
知道this的值是你避免bugs的第一步。
Javascript 相关文章推荐
再说AutoComplete自动补全之实现原理
Nov 05 Javascript
用js获取电脑信息(是使用与IE浏览器)
Jan 15 Javascript
js实现完全自定义可带多级目录的网页鼠标右键菜单方法
Feb 28 Javascript
js判断手机访问或者PC的几个例子(常用于手机跳转)
Dec 15 Javascript
Javascript 跨域知识详细介绍
Oct 30 Javascript
js中获取键盘按下键值event.keyCode、event.charCode和event.which的兼容性详解
Mar 15 Javascript
详解bootstrap导航栏.nav与.navbar区别
Nov 23 Javascript
vue elementUI 表单校验的实现代码(多层嵌套)
Nov 06 Javascript
JS实现点击下拉列表文本框中出现对应的网址,点击跳转按钮实现跳转
Nov 25 Javascript
Vue中使用Lodop插件实现打印功能的简单方法
Dec 19 Javascript
Vue中 axios delete请求参数操作
Aug 25 Javascript
vue+spring boot实现校验码功能
May 27 Vue.js
javascript 放大镜 v1.0 基于Yui2 实现的放大镜效果
Mar 08 #Javascript
JavaScript中的闭包原理分析
Mar 08 #Javascript
ExtJS GridPanel 根据条件改变字体颜色
Mar 08 #Javascript
JavaScript 滚轮事件使用说明
Mar 07 #Javascript
javascript下4个跨浏览器必备的函数
Mar 07 #Javascript
Zero Clipboard js+swf实现的复制功能使用方法
Mar 07 #Javascript
GWT中复制到剪贴板 js+flash实现复制 兼容性比较好
Mar 07 #Javascript
You might like
基于asp+ajax和数据库驱动的二级联动菜单
2010/05/06 PHP
php 文章调用类代码
2011/08/11 PHP
php日期转时间戳,指定日期转换成时间戳
2012/07/17 PHP
ThinkPHP5 框架引入 Go AOP,PHP AOP编程项目详解
2020/05/12 PHP
Jquery 滑入滑出效果实现代码
2010/03/27 Javascript
javascript客户端解决方案 缓存提供程序
2010/07/14 Javascript
firefox下frameset取不到值的解决方法
2010/09/06 Javascript
理解Javascript_11_constructor实现原理
2010/10/18 Javascript
js导航栏单击事件背景变换示例代码
2014/01/13 Javascript
js和jquery使按钮失效为不可用状态的方法
2014/01/26 Javascript
第一次接触神奇的Bootstrap基础排版
2016/07/26 Javascript
EasyUI折叠表格层次显示detailview详解及实例
2016/12/28 Javascript
js获取ip和地区
2017/03/10 Javascript
Angular4表单验证代码详解
2017/09/03 Javascript
node-sass安装失败的原因与解决方法
2017/09/04 Javascript
vue iview实现动态路由和权限验证功能
2018/04/17 Javascript
vue组件实现弹出框点击显示隐藏效果
2020/10/26 Javascript
angularjs $http调用接口的方式详解
2018/08/13 Javascript
node.js事件轮询机制原理知识点
2019/12/22 Javascript
[01:09]DOTA2次级职业联赛 - 99战队宣传片
2014/12/01 DOTA
在Python中处理字符串之isdigit()方法的使用
2015/05/18 Python
Python的地形三维可视化Matplotlib和gdal使用实例
2017/12/09 Python
Python实现PS滤镜中马赛克效果示例
2018/01/20 Python
numpy.meshgrid()理解(小结)
2019/08/01 Python
Python整数与Numpy数据溢出问题解决
2019/09/11 Python
python如何利用Mitmproxy抓包
2020/10/10 Python
Python 使用office365邮箱的示例
2020/10/29 Python
CSS3 Media Queries(响应式布局可以让你定制不同的分辨率和设备)
2013/06/06 HTML / CSS
化工专业求职信
2014/07/01 职场文书
单位委托书怎么写
2014/09/21 职场文书
保卫工作个人总结
2015/03/03 职场文书
学校国庆节活动总结
2015/03/23 职场文书
保护动物的宣传语
2015/07/13 职场文书
如何理解Vue简单状态管理之store模式
2021/05/15 Vue.js
详解Java实践之抽象工厂模式
2021/06/18 Java/Android
Python初识逻辑与if语句及用法大全
2021/08/07 Python