JavaScript 函数调用规则


Posted in Javascript onSeptember 14, 2009

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的第一步。

原文:http://devlicio.us/blogs/sergio_pereira/archive/2009/02/09/javascript-5-ways-to-call-a-function.aspx
中文翻译:http://www.yeeyan.com/articles/view/69184/30270

Javascript 相关文章推荐
JS 跳转页面延迟2种方法
Mar 29 Javascript
js 上下左右键控制焦点(示例代码)
Dec 14 Javascript
通过Javascript读取本地Excel文件内容的代码示例
Apr 08 Javascript
escape编码与unescape解码汉字出现乱码的解决方法
Jul 02 Javascript
js removeChild 方法深入理解
Aug 16 Javascript
读Javascript高性能编程重点笔记
Dec 21 Javascript
完美解决spring websocket自动断开连接再创建引发的问题
Mar 02 Javascript
vue实现移动端图片裁剪上传功能
Aug 18 Javascript
ReactNative 之FlatList使用及踩坑封装总结
Nov 29 Javascript
jQuery EasyUI 选项卡面板tabs的使用实例讲解
Dec 25 jQuery
AngularJS 应用模块化的使用
Apr 04 Javascript
JavaScript实现动态生成表格
Aug 02 Javascript
prototype与jquery下Ajax实现的差别
Sep 13 #Javascript
JS 参数传递的实际应用代码分析
Sep 13 #Javascript
javascript类继承机制的原理分析
Sep 12 #Javascript
javascript 类定义的4种方法
Sep 12 #Javascript
一个简单的javascript类定义例子
Sep 12 #Javascript
一个简单的JavaScript 日期计算算法
Sep 11 #Javascript
关于javascript 回调函数中变量作用域的讨论
Sep 11 #Javascript
You might like
php+mysqli实现批量执行插入、更新及删除数据的方法
2015/01/29 PHP
PHP闭包函数详解
2016/02/13 PHP
CodeIgniter连贯操作的底层原理分析
2016/05/17 PHP
PHP读取目录树的实现方法分析
2019/03/22 PHP
js URL参数的拼接方法比较
2012/02/15 Javascript
详解jquery uploadify 上传文件
2013/11/09 Javascript
JS清空多文本框、文本域示例代码
2014/02/24 Javascript
jQuery源码分析之jQuery中的循环技巧详解
2014/09/06 Javascript
Javascript核心读书有感之语言核心
2015/02/01 Javascript
JavaScript搜索字符串并将搜索结果返回到字符串的方法
2015/04/06 Javascript
jQuery监控文本框事件并作相应处理的方法
2015/04/16 Javascript
JS根据key值获取URL中的参数值及把URL的参数转换成json对象
2015/08/26 Javascript
JS模拟酷狗音乐播放器收缩折叠关闭效果代码
2015/10/29 Javascript
jquery实现图片轮播器
2017/05/23 jQuery
vue-baidu-map 进入页面自动定位的解决方案(推荐)
2018/04/28 Javascript
微信小程序websocket实现聊天功能
2020/03/30 Javascript
详解微信小程序之scroll-view的flex布局问题
2019/01/16 Javascript
JavaScript中callee和caller的区别与用法实例分析
2019/06/28 Javascript
《javascript设计模式》学习笔记四:Javascript面向对象程序设计链式调用实例分析
2020/04/07 Javascript
[01:56]无止竞 再出发——中国军团出征2017年DOTA2国际邀请赛
2017/07/05 DOTA
[43:24]VG vs Serenity 2018国际邀请赛小组赛BO2 第二场 8.17
2018/08/20 DOTA
python matlibplot绘制多条曲线图
2021/02/19 Python
Python+OpenCV图片局部区域像素值处理详解
2019/01/23 Python
python 调用钉钉机器人的方法
2019/02/20 Python
python在openstreetmap地图上绘制路线图的实现
2019/07/11 Python
Python装饰器实现方法及应用场景详解
2020/03/26 Python
Tensorflow tf.nn.depthwise_conv2d如何实现深度卷积的
2020/04/20 Python
Django filter动态过滤与排序实现过程解析
2020/11/26 Python
Agoda中文官网:安可达(低价预订全球酒店)
2021/01/18 全球购物
毕业生求职简历的自我评价
2013/10/07 职场文书
酒店保洁主管岗位职责
2013/11/28 职场文书
艺校音乐专业自我鉴定范文
2014/03/01 职场文书
新员工试用期自我鉴定
2014/04/17 职场文书
2014年涉外离婚协议书范本
2014/11/20 职场文书
2015年妇委会工作总结
2015/05/22 职场文书
德能勤绩工作总结
2015/08/11 职场文书