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 相关文章推荐
JS实现标签页效果(配合css)
Apr 03 Javascript
js 异步操作回调函数如何控制执行顺序
Dec 24 Javascript
jquery图片轮播插件仿支付宝2013版全屏图片幻灯片
Apr 03 Javascript
Thinkphp模板没有解析直接原样输出的解决方法
Oct 31 Javascript
js实现简洁的滑动门菜单(选项卡)效果代码
Sep 04 Javascript
jQuery实现的多滑动门,多选项卡效果代码
Mar 28 Javascript
JQuery和HTML5 Canvas实现弹幕效果
Jan 04 Javascript
vue2.0父子组件间通信的实现方法
Apr 19 Javascript
vue.js数据绑定的方法(单向、双向和一次性绑定)
Jul 13 Javascript
解决element-ui中下拉菜单子选项click事件不触发的问题
Aug 22 Javascript
JavaScript中的一些实用小技巧总结
Apr 07 Javascript
js实现随机点名功能
Dec 23 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显示MySQL数据的三种方法
2008/06/05 PHP
PHP 日志缩略名的创建函数代码
2010/05/26 PHP
PHP+mysql+ajax轻量级聊天室实现方法详解
2016/10/17 PHP
PHP查询分页的实现代码
2017/06/09 PHP
详解Yaf框架PHPUnit集成测试方法
2017/12/27 PHP
JS小框架 fly javascript framework
2009/11/26 Javascript
js 禁止选择功能实现代码(兼容IE/Firefox)
2010/04/23 Javascript
人人网javascript面试题 可以提前实现下
2012/01/05 Javascript
jQuery渐变发光导航菜单的实例代码
2013/03/27 Javascript
jQuery函数的等价原生函数代码示例
2013/05/27 Javascript
浅析JS刷新框架中的其他页面 &amp;&amp; JS刷新窗口方法汇总
2013/07/08 Javascript
jQuery post数据至ashx实例详解
2016/11/18 Javascript
Vue.js点击切换按钮改变内容的实例讲解
2018/08/22 Javascript
Nodejs模块的调用操作实例分析
2018/12/25 NodeJs
JS字符串补全方法padStart()和padEnd()
2020/05/27 Javascript
基于Vue+Webpack拆分路由文件实现管理
2020/11/16 Javascript
基于ajax实现上传图片代码示例解析
2020/12/03 Javascript
用Python实现QQ游戏大家来找茬辅助工具
2014/09/14 Python
python实现在字符串中查找子字符串的方法
2015/07/11 Python
在Mac OS上搭建Python的开发环境
2015/12/24 Python
基于Python代码编辑器的选用(详解)
2017/09/13 Python
详解Python异常处理中的Finally else的功能
2017/12/29 Python
python 实现将字典dict、列表list中的中文正常显示方法
2018/07/06 Python
python 分离文件名和路径以及分离文件名和后缀的方法
2018/10/21 Python
Python字典的基本用法实例分析【创建、增加、获取、修改、删除】
2019/03/05 Python
PHP基于phpqrcode类库生成二维码过程解析
2020/05/28 Python
Pytorch 卷积中的 Input Shape用法
2020/06/29 Python
Python filter()及reduce()函数使用方法解析
2020/09/05 Python
微软马来西亚官方网站:Microsoft马来西亚
2019/11/22 全球购物
介绍一下linux的文件系统
2012/03/20 面试题
如何开启linux的ssh服务
2015/02/14 面试题
计算机数据库专业职业生涯规划书
2014/02/08 职场文书
优秀毕业生推荐信范文
2014/03/07 职场文书
民族学专业大学生职业规划范文:清晰未来的构想
2014/09/20 职场文书
员工离职感谢信
2015/01/22 职场文书