学JS的心路历程-函式(四)apply、call
从上一篇可以知道,不同的函式呼叫会造成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的更多相关文章
- 学JS的心路历程 -函式(三)this
this是什么,取决于被呼叫的呼叫地点. 昨天有提到说,呼叫函式时候会传递隐含参数:arguments和this并讲解了arguments,今天我们就来探讨this吧! 什么是this 我们都会呼叫函 ...
- 学JS的心路历程-函式(二)arguments
参数(argument)与函式参数(parameter) 在讨论函式时,很多人都会把这两个搞混,我自己也不例外. 虽然讲错别人也听得懂,但是我们还是要搞清楚这两个的定义到底是什么! 参数是当我们呼叫函 ...
- 学JS的心路历程-函式(六)其余参数及预设参数
今天我们要来介绍ES6新增的其余参数及预设参数! 其余参数rest parameter …numbers可以让我们表示不确定数量的参数,并将其视为一个数组: function getVal(…numb ...
- 学JS的心路历程-函式(五)箭头函式
箭头函式arrow function 为了能够以更简短的方式建立函式,ES6变推出了箭头函式. 用说明的可能会不太懂,我们先拿之前的数组排序例子来看: var arr = [2,1,6,12,3,77 ...
- 学习JS的心路历程-函式(一)
前几天有间单提到该如何声明函式及在Hositing中会发生什么事,但是函式的奥妙不仅于此. 身为一个使用JS的工程师,我们一定要熟悉函式到比恋人还熟! 这几天将会把函式逐一扒开跟各位一起探讨其中的奥妙 ...
- 学JS的心路历程-JS支持面向对象?(一)
昨天在看Prototype看到JS支持面向对象,被前辈问到说那什么是面向对象?JS是面向对象语言吗? 便开始了一连串艰辛爬文过程,今天就来看一下两者有什么差异吧(rgwyjc)! 首先面向对象有三大特 ...
- 学JS的心路历程 - JS的Class
没错,你没有看错,虽然前面说JS是原型继承,但在ES6以后新增了class关键字!!! 不过底层实作仍然是以原型继承方式进行,所以基本上算是一个语法糖. 今天我们就来看一下如何使用吧! class 首 ...
- 学JS的心路历程-物件与原型(三)
昨天有说明到函式与建构式的原型,及指定建构式函式原型为另一个建构式函式,但其实这会造成复写constructor的问题. 复写constructor的问题(vmwork) 我们昨天有提到「建构式函式可 ...
- 学JS的心路历程 -物件与原型(二)
昨天有提到说Object.setPrototypeOf可以指定一个物件为另一个物件的原型,但有想过到底这个原型,也就是[[Prototype]]最终会到何处吗? 答案是Object.prototype ...
随机推荐
- spark新闻项目环境搭建
前面安装好三节点的centos 6.5 和配置好静态ip,这里就不多说了 创建kfk用户,然后重启 Last login: Fri Jan :: from 192.168.86.1 [spark@sp ...
- Windows NAT端口映射
由于有需求进行端口映射,又不想装乱七八糟的软件,Windows本身自带的路由远程访问配置太麻烦,还要两块网卡,坑爹啊. 其实Windows本身命令行支持配置端口映射,条件是已经安装了IPV6,启不启用 ...
- python-简单的sqlite3使用
# 导入SQLite驱动: >>> import sqlite3 # 连接到SQLite数据库 # 数据库文件是test.db # 如果文件不存在,会自动在当前目录创建: >& ...
- es6(16)--Decorator
//Decorator:修饰器,是一个函数用来修改类的行为 { //只读 let readonly=function(target,name,descriptor){ descriptor.writa ...
- 【Selenium-WebDriver自学】Selenium网格化(十六)
参考链接: http://www.yiibai.com/selenium/selenium_grids.html 命令: cd E:\Yingpu\000.SVNYP\01.个人文件夹\Renqian ...
- 【Jmeter自学】常见错误类型(九)
==================================================================================================== ...
- glibc -The GNU C Library
1.使用库文件 1.1.头文件 C库实际包含两部分:头文件,实际的库文件.头文件定义类型.定义宏.声明变量.声明函数.头文件定义的内容实际在库文件中实现.需要使用到 C库 的某些功能时,程序源文件包含 ...
- gentoo raid1
参考 gentoo wiki,和其他网页,实现两个硬盘组成 raid1. 两个硬盘一个是 sdc,一个是 sdd,都是 4T容量. 首先内核开启 Autodetect RAID arrays duri ...
- iframe之间通信问题及iframe自适应高度问题
下面本人来谈谈iframe之间通信问题及iframe自适应高度问题. 1. iframe通信 分为:同域通信 和 跨域通信.所谓同域通信是指 http://localhost/demo/iframe/ ...
- hping安装过程
转载: http://www.safecdn.cn/website-announcement/2018/12/hping-install/97.html Hping的主要功能有: 测试防火墙实用的 ...