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 相关文章推荐
javascript实现状态栏文字首尾相接循环滚动的方法
Jul 22 Javascript
Highcharts学习之坐标轴
Aug 02 Javascript
移动端滑动插件Swipe教程
Oct 16 Javascript
学习使用bootstrap的modal和carousel
Dec 09 Javascript
js封装tab标签页实例分享
Dec 19 Javascript
浅谈DOM的操作以及性能优化问题-重绘重排
Jan 08 Javascript
Javascript中的 “&amp;” 和 “|” 详解
Feb 02 Javascript
JS实现课堂随机点名和顺序点名
Mar 09 Javascript
通过js动态创建标签,并设置属性方法
Feb 24 Javascript
vue实现日历备忘录功能
Sep 24 Javascript
基于ajax及jQuery实现局部刷新过程解析
Sep 12 jQuery
在vue中封装的弹窗组件使用队列模式实现方法
Jul 23 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
PHP类中的魔术方法(Magic Method)简明总结
2014/07/08 PHP
PHP递归获取目录内所有文件的实现方法
2016/11/01 PHP
关于php几种字符串连接的效率比较(详解)
2017/02/22 PHP
非常棒的10款jQuery 幻灯片插件
2011/06/14 Javascript
基于jquery完美拖拽,可返回拖动轨迹
2012/03/29 Javascript
javascript实现window.print()去除页眉页脚
2014/12/30 Javascript
实例详解jQuery Mockjax 插件模拟 Ajax 请求
2016/01/12 Javascript
AngularJS中$http服务常用的应用及参数
2016/08/22 Javascript
微信小程序 WXDropDownMenu组件详解及实例代码
2016/10/24 Javascript
Node.js开启Https的实践详解
2016/10/25 Javascript
深入理解Javascript箭头函数中的this
2017/02/13 Javascript
JavaScript对象引用与赋值实例详解
2017/03/15 Javascript
angularjs中的$eval方法详解
2017/04/24 Javascript
js+html5实现页面可刷新的倒计时效果
2017/07/15 Javascript
用 Vue.js 递归组件实现可折叠的树形菜单(demo)
2017/12/25 Javascript
vue实现选项卡及选项卡切换效果
2018/04/24 Javascript
讲解vue-router之命名路由和命名视图
2018/05/28 Javascript
JQuery Ajax动态加载Table数据的实例讲解
2018/08/09 jQuery
JQuery实现简单的复选框树形结构图示例【附源码下载】
2019/07/16 jQuery
vue父子组件的通信方法(实例详解)
2019/11/10 Javascript
原生js实现表格循环滚动
2020/11/24 Javascript
Python实现屏幕截图的两种方式
2018/02/05 Python
flask框架实现连接sqlite3数据库的方法分析
2018/07/16 Python
python画柱状图--不同颜色并显示数值的方法
2018/12/13 Python
python 自动重连wifi windows的方法
2018/12/18 Python
python写日志文件操作类与应用示例
2019/07/01 Python
python线程中的同步问题及解决方法
2019/08/29 Python
python实现自动化报表功能(Oracle/plsql/Excel/多线程)
2019/12/02 Python
解决TensorFlow训练内存不断增长,进程被杀死问题
2020/02/05 Python
美国第一个网上卖鞋零售商:OnlineShoes.com
2017/09/24 全球购物
39美元购买一副眼镜或太阳镜:39DollarGlasses.com
2018/06/17 全球购物
大都会艺术博物馆商店:The Met Store
2018/06/22 全球购物
优秀中学生事迹材料
2014/01/31 职场文书
新学期教师寄语
2014/04/02 职场文书
施工单位安全责任书
2014/07/24 职场文书
JS创建或填充任意长度数组的小技巧汇总
2021/10/24 Javascript