从上一篇可以知道,不同的函式呼叫会造成this的不同,但我们能不能在呼叫时候明确指定呢?

当然可以。会有这个想法是因为往往在执行某支函式时想要用回呼函式(mizumisushi),但发现this总是显示window,为了确保this是我们想要的物件或函式,就必须使用apply及call。

可能有点难以理解,这边我们来看一个示例:

var obj = {

price:20,

sum:function(cb){

cb(100);

}

}

function getData(val){

console.log(this);

}

obj.sum(getData);//Window

可以看到我们预期getData的this是obj物件,但显示出来的却是window。

这是因为,当没有特定指明this的情况下,预设绑定(Default Binding)this为「全局物件」,也就是window。

所以除非我们透过call及apply强制指定this为自己想要的物件或函式,不然getData都会是预设的window。

就算包裹在物件内也是一样:

var obj = {

price:20,

sum:function(cb){

cb(100);

},

getData:function(val){

console.log(this,val);

}

}

obj.sum(obj.getData);//Window

好,现在我们知道call及apply可以强制指定this了,那要怎么用呢?

call及apply的作用完全一样,差别只在传入参数的方式有所不同。

call后面只接受单个值的参数,而apply只接受一个数组的参数:

var obj = {

price:20

};

function funA(x,y){

console.log(this);

console.log(x,y);

}

funA.call(obj,2,3);

//{price: 20}

//2 3

funA.apply(obj,[10,100]);

//{price: 20}

// 10 100

所以刚刚的例子我们可以这样改写:

var obj = {

price:20,

sum:function(cb){

cb.call(obj,100);

},

getData:function(val){

console.log(this,val);

}

}

obj.sum(obj.getData);

我们在第七天时有提到函式重载的示例:

function addMethod(obj,key,fn){

var old = obj[key];

obj[key] = function(){

if(fn.length === arguments.length){

return fn(arguments);

} else if(typeof old ===“function”){

return old(arguments);

}

}

}

其实这样改写会比较妥当:

function addMethod(obj,key,fn){

var old = obj[key];

obj[key] = function(){

if(fn.length === arguments.length){

return fn.apply(this,arguments);

} else if(typeof old ===“function”){

return old.apply(this,arguments);

}

}

}

以上就是call及apply的用法!

参考资料:

忍者JavaScript开发技巧探秘

重新认识JavaScript: Day 20 What's“THIS”in JavaScript

文章来源:(http://www.Lishim.com

学JS的心路历程-函式(四)apply、call的更多相关文章

  1. 学JS的心路历程 -函式(三)this

    this是什么,取决于被呼叫的呼叫地点. 昨天有提到说,呼叫函式时候会传递隐含参数:arguments和this并讲解了arguments,今天我们就来探讨this吧! 什么是this 我们都会呼叫函 ...

  2. 学JS的心路历程-函式(二)arguments

    参数(argument)与函式参数(parameter) 在讨论函式时,很多人都会把这两个搞混,我自己也不例外. 虽然讲错别人也听得懂,但是我们还是要搞清楚这两个的定义到底是什么! 参数是当我们呼叫函 ...

  3. 学JS的心路历程-函式(六)其余参数及预设参数

    今天我们要来介绍ES6新增的其余参数及预设参数! 其余参数rest parameter …numbers可以让我们表示不确定数量的参数,并将其视为一个数组: function getVal(…numb ...

  4. 学JS的心路历程-函式(五)箭头函式

    箭头函式arrow function 为了能够以更简短的方式建立函式,ES6变推出了箭头函式. 用说明的可能会不太懂,我们先拿之前的数组排序例子来看: var arr = [2,1,6,12,3,77 ...

  5. 学习JS的心路历程-函式(一)

    前几天有间单提到该如何声明函式及在Hositing中会发生什么事,但是函式的奥妙不仅于此. 身为一个使用JS的工程师,我们一定要熟悉函式到比恋人还熟! 这几天将会把函式逐一扒开跟各位一起探讨其中的奥妙 ...

  6. 学JS的心路历程-JS支持面向对象?(一)

    昨天在看Prototype看到JS支持面向对象,被前辈问到说那什么是面向对象?JS是面向对象语言吗? 便开始了一连串艰辛爬文过程,今天就来看一下两者有什么差异吧(rgwyjc)! 首先面向对象有三大特 ...

  7. 学JS的心路历程 - JS的Class

    没错,你没有看错,虽然前面说JS是原型继承,但在ES6以后新增了class关键字!!! 不过底层实作仍然是以原型继承方式进行,所以基本上算是一个语法糖. 今天我们就来看一下如何使用吧! class 首 ...

  8. 学JS的心路历程-物件与原型(三)

    昨天有说明到函式与建构式的原型,及指定建构式函式原型为另一个建构式函式,但其实这会造成复写constructor的问题. 复写constructor的问题(vmwork) 我们昨天有提到「建构式函式可 ...

  9. 学JS的心路历程 -物件与原型(二)

    昨天有提到说Object.setPrototypeOf可以指定一个物件为另一个物件的原型,但有想过到底这个原型,也就是[[Prototype]]最终会到何处吗? 答案是Object.prototype ...

随机推荐

  1. 各种波形文件VCD,VPD,SHM,FSDB生成的方法

    转载---http://www.cnblogs.com/zeushuang/archive/2012/11/14/2769640.html 仿真是IC设计不可或缺的重要步骤,仿真后一般需要记录下波形文 ...

  2. centos7 图形化界面

    当你安装centos服务器版本的时候,系统默认是不会安装 CentOS 的图形界面程序的,比如:gnome或者kde, 那么如果你想在图形界面下工作的话,可以手动来安装CentOS Gnome GUI ...

  3. 关于{get;set;}访问器

    /// <summary> /// 此视频更新时间/创建时间 [生成时间,不手填] /// </summary> public System.String CreateTime ...

  4. CentOS7离线安装TIDB

    首先准备一台能够联网,并且操作系统版本与正式版本完全一致的服务器. 安装思路是,通过在线方式获得所有离线安装包,然后导入到正式安装环境中去. yum install -y --downloadonly ...

  5. Unity3D Update() 和 FixedUpdate()区别

    Unity3D中 Update()与FixedUpdate()的区别是什么呢?从字面上理解,它们都是在更新时会被调用,并且会循环的调用.但是Update会在每次渲 染新的一帧时,被调用.而FixedU ...

  6. zookeeper(4)--zookeeper分布式锁原理

    目前几乎很多大型网站及应用都是分布式部署的,分布式场景中的数据一致性问题一直是一个比较重要的话题.分布式的CAP理论告诉我们“任何一个分布式系统都无法同时满足一致性(Consistency).可用性( ...

  7. module模块和包

    import 和 from 调用 module 目录有calc.py 和  test.py 两个文件 calc.py文件内容: def add(x,z): return x+z def sub(x,z ...

  8. 机器学习进阶-项目实战-信用卡数字识别 1.cv2.findContour(找出轮廓) 2.cv2.boudingRect(轮廓外接矩阵位置) 3.cv2.threshold(图片二值化操作) 4.cv2.MORPH_TOPHAT(礼帽运算突出线条) 5.cv2.MORPH_CLOSE(闭运算图片内部膨胀) 6. cv2.resize(改变图像大小) 7.cv2.putText(在图片上放上文本)

    7. cv2.putText(img, text, loc, text_font, font_scale, color, linestick) # 参数说明:img表示输入图片,text表示需要填写的 ...

  9. mysql存储过程使用游标循环插入数据

    DELIMITER $$ DROP PROCEDURE IF EXISTS `procedure_course`$$ CREATE DEFINER=`root`@`localhost` PROCEDU ...

  10. ACM__菜鸟之经典错误

    1:多组输入与单组输入 Input contains multiple test cases. Input contains a single test case. 2:  EOF=-1 while( ...