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 相关文章推荐
悄悄用脚本检查你访问过哪些网站的代码
Dec 04 Javascript
简单几行JS Code实现IE邮件转发新浪微博
Jul 03 Javascript
js弹出div并显示遮罩层
Feb 12 Javascript
jQuery实现鼠标经过事件的延时处理效果
Aug 20 Javascript
手机端 HTML5使用photoswipe.js仿微信朋友圈图片放大效果
Aug 25 Javascript
浅谈事件冒泡、事件委托、jQuery元素节点操作、滚轮事件与函数节流
Jul 22 jQuery
webstrom Debug 调试vue项目的方法步骤
Jul 17 Javascript
vue+axios+mock.js环境搭建的方法步骤
Aug 28 Javascript
vue  自定义组件实现通讯录功能
Sep 30 Javascript
node使用Mongoose类库实现简单的增删改查
Nov 08 Javascript
vue3.0中setup使用(两种用法)
Dec 02 Vue.js
JS中forEach()、map()、every()、some()和filter()的用法
May 11 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获取类中常量,属性,及方法列表的方法
2009/04/09 PHP
php Hex RGB颜色值互换的使用
2013/05/10 PHP
兼容PHP和Java的des加密解密代码分享
2014/06/26 PHP
php提供实现反射的方法和实例代码
2019/09/17 PHP
利用javascript实现web页面中指定区域打印
2013/10/30 Javascript
javascript阻止scroll事件多次执行的思路及实现
2013/11/08 Javascript
javascript使用正则控制input输入框允许输入的值方法大全
2014/06/19 Javascript
全面解析Bootstrap排版使用方法(文字样式)
2015/11/30 Javascript
FullCalendar日历插件应用之数据展现(一)
2015/12/23 Javascript
jQuery AJAX timeout 超时问题详解
2016/06/21 Javascript
AngularJS通过$sce输出html的方法
2016/09/22 Javascript
JS实现简易的图片拖拽排序实例代码
2017/06/09 Javascript
AngularJS2 与 D3.js集成实现自定义可视化的方法
2017/12/01 Javascript
JS简单获得节点元素的方法示例
2018/02/10 Javascript
vue写一个组件
2018/04/09 Javascript
scrapyd schedule.json setting 传入多个值问题
2019/08/07 Javascript
vue中使用vee-validator完成表单校验方案
2019/11/01 Javascript
解决vue-photo-preview 异步图片放大失效的问题
2020/07/29 Javascript
vue+高德地图实现地图搜索及点击定位操作
2020/09/09 Javascript
vue实现下拉菜单树
2020/10/22 Javascript
python3解析库BeautifulSoup4的安装配置与基本用法
2018/06/26 Python
vue.js实现输入框输入值内容实时响应变化示例
2018/07/07 Python
PythonWeb项目Django部署在Ubuntu18.04腾讯云主机上
2019/04/01 Python
Python django框架应用中实现获取访问者ip地址示例
2019/05/17 Python
python将字母转化为数字实例方法
2019/10/04 Python
Django 博客实现简单的全文搜索的示例代码
2020/02/17 Python
Lands’ End官网:经典的美国生活方式品牌
2016/08/14 全球购物
台湾东南旅游社网站:东南旅游
2019/02/11 全球购物
美国庭院家具购物网站:AlphaMarts
2019/04/10 全球购物
父亲生日宴会答谢词
2014/01/10 职场文书
亲属关系公证书
2014/04/08 职场文书
餐厅周年庆活动方案
2014/08/25 职场文书
三十年同学聚会感言
2015/07/30 职场文书
《围炉夜话》110句人生箴言,精辟有内涵,引人深思
2019/10/23 职场文书
nginx如何将http访问的网站改成https访问
2021/03/31 Servers
Nginx进程调度问题详解
2021/09/25 Servers