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 相关文章推荐
javascipt基础内容--需要注意的细节
Apr 10 Javascript
JS实现QQ图片一闪一闪的效果小例子
Jul 31 Javascript
jquery实现背景墙聚光灯效果示例分享
Mar 02 Javascript
jquery 取子节点及当前节点属性值的方法
Aug 24 Javascript
js实现固定显示区域内自动缩放图片的方法
Jul 18 Javascript
JS实现1000以内被3或5整除的数字之和
Feb 18 Javascript
原生js实现ajax方法(超简单)
Sep 20 Javascript
easyui关于validatebox实现多重规则验证的方法(必看)
Apr 12 Javascript
详解Vue 开发模式下跨域问题
Jun 06 Javascript
JavaScript截屏功能的实现代码
Jul 28 Javascript
详解如何用babel转换es6的class语法
Apr 03 Javascript
vue项目配置使用flow类型检查的步骤
Mar 18 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
zf框架的session会话周期及次数限制使用示例
2014/03/13 PHP
php计算税后工资的方法
2015/07/28 PHP
thinkphp5使用无限极分类
2019/02/18 PHP
laravel配置Redis多个库的实现方法
2019/04/10 PHP
详解PHP PDO简单教程
2019/05/28 PHP
laravel 模型查询按照whereIn排序的示例
2019/10/16 PHP
JQuery将文本转化成JSON对象需要注意的问题
2011/05/09 Javascript
js函数调用的方式
2014/05/06 Javascript
多个$(document).ready()的执行顺序实例分析
2014/07/26 Javascript
ajaxFileUpload.js插件支持多文件上传的方法
2014/09/02 Javascript
jQuery中:first-child选择器用法实例
2014/12/31 Javascript
jQuery判断对象是否存在的方法
2015/02/05 Javascript
深入理解JavaScript系列(17):面向对象编程之概论详细介绍
2015/03/04 Javascript
jQuery实现可编辑的表格实例讲解(2)
2015/09/17 Javascript
原生javascript上传图片带进度条【实例分享】
2017/04/06 Javascript
json的结构与遍历方法实例分析
2017/04/25 Javascript
Three.js入门之hello world以及如何绘制线
2017/09/25 Javascript
浅谈ajax请求不同页面的微信JSSDK问题
2018/02/26 Javascript
JS实现的3des+base64加密解密算法完整示例
2018/05/18 Javascript
vue组件定义,全局、局部组件,配合模板及动态组件功能示例
2019/03/19 Javascript
基于vue-cli 路由 实现类似tab切换效果(vue 2.0)
2019/05/08 Javascript
Vue-drag-resize 拖拽缩放插件的使用(简单示例)
2019/12/04 Javascript
python实现查询苹果手机维修进度
2015/03/16 Python
Python脚本实现格式化css文件
2015/04/08 Python
Win7下搭建python开发环境图文教程(安装Python、pip、解释器)
2016/05/17 Python
python爬虫系列Selenium定向爬取虎扑篮球图片详解
2017/11/15 Python
利用Django-environ如何区分不同环境
2018/08/26 Python
Python classmethod装饰器原理及用法解析
2020/10/17 Python
CSS3中使用RGBA设置透明度的示例
2015/08/04 HTML / CSS
初三家长会邀请函
2014/01/18 职场文书
优乐美广告词
2014/03/14 职场文书
高中生第一学年自我鉴定
2014/09/12 职场文书
幼儿园见习报告范文
2014/10/30 职场文书
商超业务员岗位职责
2015/02/13 职场文书
企业工会工作总结2015
2015/05/13 职场文书
html form表单基础入门案例讲解
2021/07/21 HTML / CSS