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 相关文章推荐
Jquery显示、隐藏元素以及添加删除样式
Aug 09 Javascript
js密码强度校验
Nov 10 Javascript
详解RequireJS按需加载样式文件
Apr 12 Javascript
Angular2学习笔记之数据绑定的示例代码
Jan 03 Javascript
vue脚手架中配置Sass的方法
Jan 04 Javascript
详解Angular结合zTree异步加载节点数据
Jan 20 Javascript
快速解决vue-cli不能初始化webpack模板的问题
Mar 20 Javascript
JavaScript callback回调函数用法实例分析
May 08 Javascript
浅谈在不使用ssr的情况下解决Vue单页面SEO问题(2)
Nov 08 Javascript
webpack4实现不同的导出类型
Apr 09 Javascript
js实现简单页面全屏
Sep 17 Javascript
多种类型jQuery网页验证码插件代码实例
Jan 09 jQuery
初识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
php递归方法实现无限分类实例代码
2014/02/28 PHP
IIS6.0 开启Gzip方法及PHP Gzip函数分享
2014/06/08 PHP
php判断访问IP的方法
2015/06/19 PHP
Zend Framework教程之模型Model用法简单实例
2016/03/04 PHP
Javascript实现CheckBox的全选与取消全选的代码
2010/07/20 Javascript
使用jquery mobile做幻灯播放效果实现步骤
2013/01/04 Javascript
jQuery中filter()和find()的区别深入了解
2013/09/25 Javascript
JS 数字转换研究总结
2013/12/26 Javascript
jquery原创弹出层折叠效果点击折叠弹出一个层
2014/03/12 Javascript
jQuery中remove()方法用法实例
2014/12/25 Javascript
JS弹出对话框实现方法(三种方式)
2015/12/18 Javascript
ReactJs快速入门教程(精华版)
2016/11/28 Javascript
EditPlus 正则表达式 实战(3)
2016/12/15 Javascript
用 Vue.js 递归组件实现可折叠的树形菜单(demo)
2017/12/25 Javascript
浅谈Vue下使用百度地图的简易方法
2018/03/23 Javascript
使用Vue 实现滑动验证码功能
2019/06/27 Javascript
python装饰器decorator介绍
2014/11/21 Python
Python实现两个list对应元素相减操作示例
2017/06/09 Python
Python栈算法的实现与简单应用示例
2017/11/01 Python
python清理子进程机制剖析
2017/11/23 Python
Django2.1.3 中间件使用详解
2018/11/26 Python
使用Python-OpenCV向图片添加噪声的实现(高斯噪声、椒盐噪声)
2019/05/28 Python
利用anaconda保证64位和32位的python共存
2021/03/09 Python
Python通过4种方式实现进程数据通信
2020/03/12 Python
解决img标签上下出现间隙的方法
2016/12/14 HTML / CSS
数以千计的折扣工业产品:ESE Direct
2018/05/20 全球购物
STP协议的主要用途是什么?为什么要用STP
2012/12/20 面试题
软件测试企业面试试卷
2016/07/13 面试题
学习2014年全国两会心得体会
2014/03/12 职场文书
供应链金融服务方案
2014/05/25 职场文书
工程负责人任命书
2014/06/06 职场文书
四年级学生期末评语
2014/12/26 职场文书
三好学生个人总结
2015/02/15 职场文书
春季运动会加油词
2015/07/18 职场文书
Golang 空map和未初始化map的注意事项说明
2021/04/29 Golang
spring IOC容器的Bean管理XML自动装配过程
2022/05/30 Java/Android