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 表单的友好用户体现
Jan 07 Javascript
jQuery对表单的操作代码集合
Apr 06 Javascript
游览器中javascript的执行过程(图文)
May 20 Javascript
JavaScript 中的日期和时间及表示标准介绍
Aug 21 Javascript
JavaScript实现url地址自动检测并添加URL链接示例代码
Nov 12 Javascript
jquery插件NProgress.js制作网页加载进度条
Jun 05 Javascript
pace.js页面加载进度条插件
Sep 29 Javascript
javascript封装addLoadEvent实现页面同时加载执行多个函数的方法
Jul 25 Javascript
AngularJS中比较两个数组是否相同
Aug 24 Javascript
jQuery实现的手动拖动控制进度条效果示例【测试可用】
Apr 18 jQuery
javascript设计模式 ? 享元模式原理与用法实例分析
Apr 15 Javascript
微信小程序实现转盘抽奖
Sep 21 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来与ODBC数据连接
2006/10/09 PHP
Apache2中实现多网站域名绑定的实现方法
2011/06/01 PHP
解析mysql 表中的碎片产生原因以及清理
2013/06/22 PHP
php正则preg_replace_callback函数用法实例
2015/06/01 PHP
PHP实现简单的新闻发布系统实例
2015/07/28 PHP
php使用mysqli和pdo扩展,测试对比mysql数据库的执行效率完整示例
2019/05/09 PHP
js创建一个input数组并绑定click事件的方法
2014/06/12 Javascript
jQuery插件slicebox实现3D动画图片轮播切换特效
2015/04/12 Javascript
基于Bootstrap漂亮简洁的CSS3价格表(附源码下载)
2017/02/28 Javascript
微信小程序 swiper组件构建轮播图的实例
2017/09/20 Javascript
JavaScript作用域链实例详解
2019/01/21 Javascript
浅谈javascript中的prototype和__proto__的理解
2019/04/07 Javascript
python中的错误处理
2016/04/10 Python
Python温度转换实例分析
2018/01/17 Python
django启动uwsgi报错的解决方法
2018/04/08 Python
用Python和WordCloud绘制词云的实现方法(内附让字体清晰的秘笈)
2019/01/08 Python
python django 原生sql 获取数据的例子
2019/08/14 Python
pycharm激活码快速激活及使用步骤
2020/03/12 Python
tensorflow 2.0模式下训练的模型转成 tf1.x 版本的pb模型实例
2020/06/22 Python
Python接口测试环境搭建过程详解
2020/06/29 Python
菲律宾旅游网站:Expedia菲律宾
2017/10/11 全球购物
美国在线家具网站:GDFStudio
2021/03/13 全球购物
什么是Oracle的后台进程background processes?都有哪些后台进程?
2012/04/26 面试题
会计电算化个人自我评价
2013/11/17 职场文书
仓库管理专业个人的自我评价
2013/12/30 职场文书
护理个人求职信范文
2014/01/08 职场文书
五一手机促销方案
2014/03/08 职场文书
2014年社会实践活动总结范文
2014/04/29 职场文书
教师党的群众路线教育实践活动个人对照检查材料
2014/09/23 职场文书
自我检讨书怎么写
2015/05/07 职场文书
2015年幼儿园卫生保健工作总结
2015/05/12 职场文书
实验心得体会范文
2016/01/25 职场文书
Mysql systemctl start mysqld报错的问题解决
2021/06/03 MySQL
阿里云k8s服务升级时502错误 springboot项目应用
2022/04/09 Servers
Tomcat安装使用及部署Web项目的3种方法汇总
2022/08/14 Servers
Python创建SQL数据库流程逐步讲解
2022/09/23 Python