javascript 函数调用的对象和方法


Posted in Javascript onJuly 01, 2010

如果你真正理解Javascript函数是如何调用工作的,那么就可以避免一些bug的发生;
首先让我们创建一个简单的函数,这个函数将在下文中使用,这个函数仅仅返回当前的this的值和两个提供的参数.

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

调用这个函数非常的简单,我们需要做的仅仅是:
makeArray('one', 'two');

返回值:=> [ window, 'one', 'two' ]
问题出现了,this的值怎么会变成了window?下面做个简单分析:
在Javascript里,有一个全局的对象, 那些看起来散落在你的脚本里的每一行代码,其实都被写在了一个全局对象的上下文里.在我们的例子中,其实那个makeArray 函数可以说不是一个松散的全局函数,而是全局对象的一个方法, 让我们返回来看浏览器,在这个环境里它的全局对象被映射到window对象.让我们来证明一下:
alert( typeof window.makeArray);

返回值:=> function

所有的这些意味着我们之前调用makeArray的方法是和下面调用的方法一样的,

window.makeArray('one', 'two');

返回值:=> [ window, 'one', 'two' ]

JavaScript函数调用规则1:在没有通过明确所有者对象而直接调用的函数中,如myFunction(),将导致this的值成为默认对象(浏览器中的窗口)。

现创建一个简单的对象,使用makeArray函数作为它的一个方法,我们将使用json的方式来声明一个对象,我们也来调用这个方法:

var arrayMaker = { 
someProperty: 'some value here', 
make: makeArray 
}; 
arrayMaker.make('one', 'two'); 
// 返回:=> [ arrayMaker, 'one', 'two' ] 
arrayMaker['make']('one', 'two'); 
// 返回:=> [ arrayMaker, 'one', 'two' ]

this的值变成了对象arrayMaker本身.你可能会疑问原始的函数定义并没有改变,为何它不是window了呢.函数是一个对象,你可以传递它们或者复制他们.就好像整个函数连带参数列表和函数体都被复制,且被分配给了arrayMaker里的属性make,那就好像这样定义一个arrayMaker:
var arrayMaker = { 
someProperty: 'some value here', 
make: function (arg1, arg2) {return [ this, arg1, arg2 ];} 
};

JavaScript函数调用规则2: 在一个使用方法调用语法,像 obj.myFunction()或者 obj['myFunction'](),这时this的值为obj。

这是事件处理代码中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; 
//返回值:=> btn1,它是一个方法调用,this为所属的对象(按钮元素) 
button2.onclick = function(){buttonClicked();}; 
//返回值:=> window ,因为buttonClicked()是被直接调用的(不像 obj.buttonClicked().) 这和我们第三个按钮,将事件处理函数直接放在标签里是一样的.所以点击第三个按钮的结果是和第二个一样,都是window. 
</script>

我们知道在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' ]

值得注意的是出现在函数调用前面的new运算符,没有它,函数就像全局函数一样,且我们创建的那些属性都将是创建在全局对象上(window),而你并不想那样,另一个话题是,因为在你的构造器里没有返回值,所以如果你忘记使用new运算符,将导致你的一些变量被赋值为 undefined.因为这个原因,构造器函数以大写字母开头是一个好的习惯,这可以作为一个提醒,让你在调用的时候不要忘记前面的new运算符.

Javascript函数调用规则3: 当你将函数用作初始化函数的时候,像MyFunction(),Javascript的运行时将把this的值指定为新建的对象.

Javascript 相关文章推荐
javascript实现的网页局布刷新效果
Dec 01 Javascript
IE FF OPERA都可用的弹出层实现代码
Sep 29 Javascript
jQuery UI Dialog 创建友好的弹出对话框实现代码
Apr 12 Javascript
对JavaScript客户端应用编程的一些建议
Jun 24 Javascript
理解javascript正则表达式
Mar 08 Javascript
基于MVC+EasyUI的web开发框架之使用云打印控件C-Lodop打印页面或套打报关运单信息
Aug 29 Javascript
jQuery实现侧浮窗与中浮窗切换效果的方法
Sep 05 Javascript
AngularJS监听路由的变化示例代码
Sep 23 Javascript
基于javascript实现按圆形排列DIV元素(三)
Dec 02 Javascript
JavaScript中校验银行卡号的实现代码
Dec 19 Javascript
100多个基础常用JS函数和语法集合大全
Feb 16 Javascript
vue实现页面内容禁止选中功能,仅输入框和文本域可选
Nov 09 Javascript
this和执行上下文实现代码
Jul 01 #Javascript
jquery.validate使用攻略 第五步 正则验证
Jul 01 #Javascript
jquery validate使用攻略 第四步
Jul 01 #Javascript
jquery.validate使用攻略 第三部
Jul 01 #Javascript
jquery.validate使用攻略 第二部
Jul 01 #Javascript
jQuery Validation插件remote验证方式的Bug解决
Jul 01 #Javascript
jquery.validate使用攻略 第一部
Jul 01 #Javascript
You might like
php&amp;java(二)
2006/10/09 PHP
phpmyadmin MySQL 加密配置方法
2009/07/05 PHP
redis 队列操作的例子(php)
2012/04/12 PHP
PHP实现文件下载详解
2014/11/27 PHP
Thinkphp 在api开发中异常返回依然是html的解决方式
2019/10/16 PHP
JavaScript实际应用:innerHTMl和确认提示的使用
2006/06/22 Javascript
js 图片缩放(按比例)控制代码
2009/05/27 Javascript
让FireFox支持innerText的实现代码
2009/12/01 Javascript
BOM与DOM的区别分析
2010/10/26 Javascript
JavaScript面向对象之Prototypes和继承
2012/07/12 Javascript
js禁止document element对象选中文本实现代码
2013/03/21 Javascript
基于dom编程中 动态创建与删除元素的使用
2013/04/17 Javascript
node+express+jade制作简单网站指南
2014/11/26 Javascript
javascript属性访问表达式用法分析
2015/04/25 Javascript
Javascript技术难点之apply,call与this之间的衔接
2015/12/04 Javascript
强大Vue.js组件浅析
2016/09/12 Javascript
再谈javascript注入 黑客必备!
2016/09/14 Javascript
vue+vux实现移动端文件上传样式
2017/07/28 Javascript
vue interceptor 使用教程实例详解
2018/09/13 Javascript
vue单页应用在页面刷新时保留状态数据的方法
2018/09/21 Javascript
python中lambda函数 list comprehension 和 zip函数使用指南
2014/09/28 Python
python机器学习之神经网络(三)
2017/12/20 Python
Python快速查找list中相同部分的方法
2018/06/27 Python
Django使用模板后无法找到静态资源文件问题解决
2019/07/19 Python
pandas 对日期类型数据的处理方法详解
2019/08/08 Python
Python threading.local代码实例及原理解析
2020/03/16 Python
Python列表去重复项的N种方法(实例代码)
2020/05/12 Python
Django def clean()函数对表单中的数据进行验证操作
2020/07/09 Python
武汉世纪畅想数字传播有限公司.NET笔试题
2014/07/22 面试题
通用C#笔试题附答案
2016/11/26 面试题
外贸学院会计专业应届生求职信
2013/11/14 职场文书
导游的职业规划书范文
2013/12/27 职场文书
公司总经理岗位职责
2015/04/01 职场文书
Matlab求解数组中的最大值及它所在的具体位置
2021/04/16 Python
纯html+css实现打字效果
2021/08/02 HTML / CSS
Python中的 enumerate和zip详情
2022/05/30 Python