Javascript调用函数方法的几种方式介绍


Posted in Javascript onMarch 20, 2015

javascript语法灵活,同一个功能有五六种实现方式并不罕见,然后再加上有些反人类的原型继承和异步特性,就更让人一头雾水了。我经常搞不清楚call,apply之间的区别,今天就记录一下,以免再忘了。

在javascript中,方法可以通过以下几种方式执行:

1.func(),这是最直接最常见的调用方式,也符合一般人的思维逻辑,但是在某些情况下有一些不足,下面会解释。

2.(function(arg){})(window),匿名方法调用,在构造命名空间时比较有用,后面的括号中的参数与匿名方法中的入参一一对应。

3.func.bind(sth)(),mozilla手册中提到bind是在ECMA-262 5th Edition中新增的一个特性,这里单独列出来作为一种调用方式是因为它弥补了直接调用中不能绑定作用域的缺陷。

4.func.call(),这是第二种调用方式,每个方法的原型中都定义了call方法,用来执行当前方法。

5.func.apply(),call的双胞胎兄弟。

func()

这是最常见的调用方式,在任何语言中随处可见。func(x, y)可以传入不同的参数。在某些语言,例如php,java中,这种调用足以解决一切问题。但是javascript是一门函数式语言,闭包的概念和一个奇怪的关键词this决定了这种调用方式的不足。this应该可以解释为当前代码段的作用域,会随着代码执行到不同的片段而改变,但是某些情况下我们不希望这个this被改变,例如绑定在某些dom上的事件,我们肯定不希望他们被调用的时候this被转移到了window对象上,但有时候确实如此,再比如下面的代码。

var a ={};

var func = function(x) {

    console.log(this);

};

a.onclick = function() {

    var x = 100;

    func(x);

};

a.onclick();

可以把a想象成页面中的一个链接,由于我们只是想将定义好的方法绑定到onclick事件上,而不是立刻调用它,而且这个方法拥有一个参数,所以我们需要用一个匿名方法将他包起来传递给a的onclick事件。这样就有了一个问题,func中的this变成了全局对象window,显然我们并不希望如此。这个时候,使用func()这种直接调用的方式就不行了,于是我们需要将func外的this绑定到func方法上。于是就有了bind,call,apply方法。

bind

bind的目的非常简单,返回一个绑定了this对象的相同方法。上面的代码修改一行就可以实现绑定this在a对象上目的。

var a ={};

var func = function(x) {

    console.log(this);

};

a.onclick = function() {

    var x = 100;

    func.bind(this)(x);  // bind here

};

a.onclick();

这样,onclick事件的this就不会像无头苍蝇一样到处乱跑啦。

call & apply

call和apply要放在一起讲,因为他们实在太像了。他们都支持多参数,而且第一个参数都是即将绑定的this对象,第二个参数则是他们的区别所在,call使用独立的参数作为调用方法的入参,apply使用一个数组作为入参。有的时候我们并不是不想改变this对象,而是想人为的将他绑定到别的对象上,这个时候call和apply是很好用的。(并不是说不能用bind,不过貌似bind出现的比较晚,可能浏览器兼容性不好)。举个栗子:

a = {

    func: function() {

              this.x += 1;

          },

    x: 0

};

b = {

    a: a,

    x: 20

};

for(var i = 0; i < 10; i++){

    b.a.func();

}

console.log(a.x);

console.log(b.x);

上面的a和b对象中都有x,我们希望func能针对性的修改对应的x,但是直接调用只可能修改func作用域中的x,也就是a.x。修改一下代码,就可以实现修改b.x目的

a = {

    func: function() {

              this.x += 1;

          },

    x: 0

};

b = {

    a: a,

    x: 20

};

for(var i = 0; i < 10; i++){

    b.a.func.call(b);  // bind this to b

}

console.log(a.x);

console.log(b.x);

这个栗子举得不好,有点牵强附会,而且这是一种很容易让人迷惑的代码风格,有适用的场景,但不是处处都可用。

Javascript 相关文章推荐
js内置对象 学习笔记
Aug 01 Javascript
UpdatePanel和Jquery冲突的解决方法
Apr 01 Javascript
jQuery父级以及同级元素查找介绍
Sep 04 Javascript
JavaScript中使用concat()方法拼接字符串的教程
Jun 06 Javascript
JavaScript中的slice()方法使用详解
Jun 06 Javascript
jQuery实现的简洁下拉菜单导航效果代码
Aug 26 Javascript
jQuery+css实现炫目的动态块漂移效果
Jan 28 Javascript
jQuery实现百叶窗焦点图动画效果代码分享(附源码下载)
Mar 14 Javascript
微信公众号开发 实现点击返回按钮就返回到聊天界面
Dec 15 Javascript
深入理解Vue keep-alive及实践总结
Aug 21 Javascript
layui多iframe页面控制定时器运行的方法
Sep 05 Javascript
解决vue动态路由异步加载import组件,加载不到module的问题
Jul 26 Javascript
初识Node.js
Mar 20 #Javascript
JavaScript Sort 的一个错误用法示例
Mar 20 #Javascript
JS实现的数组全排列输出算法
Mar 19 #Javascript
JavaScript在浏览器标题栏上显示当前日期和时间的方法
Mar 19 #Javascript
JavaScript实现在标题栏上显示当前日期的方法
Mar 19 #Javascript
JavaScript显示当前文档最后修改日期的方法
Mar 19 #Javascript
JavaScript将一个数组插入到另一个数组的方法
Mar 19 #Javascript
You might like
了解Joomla 这款来自国外的php网站管理系统
2010/03/11 PHP
php目录操作函数之获取目录与文件的类型
2010/12/29 PHP
PHP伪造来源HTTP_REFERER的方法实例详解
2015/07/06 PHP
PHP实现添加购物车功能
2017/03/06 PHP
ExtJS4中的requires使用方法示例介绍
2013/12/03 Javascript
jquery map方法使用示例
2014/04/23 Javascript
jQuery插件实现无缝滚动特效
2015/11/24 Javascript
js复制内容到剪贴板代码,js复制代码的简单实例
2016/10/27 Javascript
Bootstrap 手风琴菜单的实现代码
2017/01/20 Javascript
微信小程序上滑加载下拉刷新(onscrollLower)分批加载数据(二)
2017/05/11 Javascript
Layer弹出层动态获取数据的方法
2018/08/20 Javascript
JavaScript 高性能数组去重的方法
2018/09/20 Javascript
基于JavaScript实现每日签到打卡轨迹功能
2018/11/29 Javascript
JS判断两个数组或对象是否相同的方法示例
2019/02/28 Javascript
vue的keep-alive中使用EventBus的方法
2019/04/23 Javascript
Easyui 关闭jquery-easui tab标签页前触发事件的解决方法
2019/04/28 jQuery
vue-cli3 配置开发与测试环境详解
2019/05/17 Javascript
ant design vue嵌套表格及表格内部编辑的用法说明
2020/10/28 Javascript
[01:02]2014 DOTA2国际邀请赛中国区预选赛 现场抢先看
2014/05/22 DOTA
Python查看多台服务器进程的脚本分享
2014/06/11 Python
Python 字典dict使用介绍
2014/11/30 Python
Python实现身份证号码解析
2015/09/01 Python
flask + pymysql操作Mysql数据库的实例
2017/11/13 Python
用python统计代码行的示例(包括空行和注释)
2018/07/24 Python
记一次python 内存泄漏问题及解决过程
2018/11/29 Python
python矩阵的转置和逆转实例
2018/12/12 Python
使用python进行波形及频谱绘制的方法
2019/06/17 Python
PyCharm中代码字体大小调整方法
2019/07/29 Python
Python通过socketserver处理多个链接
2020/03/18 Python
.NET面试题:什么是反射
2016/09/30 面试题
销售人员中英文自荐信
2013/09/22 职场文书
好人好事事迹材料
2014/02/12 职场文书
终止劳动合同协议书
2014/04/14 职场文书
岗位说明书怎么写
2014/07/30 职场文书
2015年党员创先争优承诺书
2015/01/22 职场文书
银行柜员优质服务心得体会
2016/01/22 职场文书