JavaScript中的call和apply应用
ECMAScript3给
Function的原型定义了两个方法,他们是Function.prototype.call和Function.prototype.apply. 在实际开发中,特别是在一些函数式风格的代码编写中,call和apply方法尤为有用。
call和apply区别
其实他们的作用是一样的,只是传递的参数不一样而已。
apply: 接受2个参数,第一个参数指定了函数体内this对象的指向,第二个参数为数组或者一个类数组。apply传入的是一个参数数组,也就是将多个参数组合成为一个数组传入,而call则作为call的参数传入(从第二个参数开始)。
举个栗子:
|
const obj1 = {
name: 'microzz',
getName: function() {
return this.name;
}
};
const obj2 = {
name: 'Zhaohui'
}
console.log(obj1.getName()); // "microzz"
console.log(obj1.getName.call(obj2)); // "Zhaohui"
console.log(obj1.getName.apply(obj2)); // "Zhaohui"
|
call和apply的用途
改变this指向
call和apply可以改变this的指向,这点我们从上面这个例子中可以看出。我们还可以举一个实际当中可以遇到的情况:
有的时候我们会觉得 document.getElementById这个方法太长了,我们会尝试用一个短函数来代替它,如同prototype.js等一些框架所做过的事情,下面用代码说明:
|
const getId = function(id) {
return document.getElementById(id);
}
getId('id');
|
在Chrome、Firefox、IE10中执行会发现抛出异常,这是因为很多引擎的 document.getElementById 的方法内部需要用到this,这个this本来被期望指向document,但直接普通函数调用就指向了window。我们可以利用apply“修正” this:
|
document.getElementById = (function(func) {
return function() {
return func.apply(document, arguments);
}
})(document.getElement);
const getId = document.getElementById;
|
Function.prototype.bind
在大部分高级浏览器已经实现了内置的Function.prototype.bind,用来指定函数内部的this指向,如果没有原生的Function.prototype.bind,我们也可以模拟一个,代码如下:
|
Function.prototype.bind = function(context) {
var self = this;
return function() {
return self.apply(context, arguments);
}
}
var obj = {
name: 'microzz'
};
var func = function() {
console.log(this.name); // microzz
}.bind(obj);
func();
|
这是一个简化版的,通常我们会实现得稍微复杂一点:
|
Function.prototype.bind = function() {
var self = this;
// 需要绑定的this上下文
var context = [].shift.call(arguments);
// 剩余的参数转成数组
var args = [].slice.call(arguments);
return function() {
return self.apply(context, [].concat.call(args, [].slice.call(arguments)));
}
}
var obj = {
name: 'microzz'
};
var func = function(a, b, c, d) {
console.log(this.name); // microzz
console.log([a, b, c, d]); // [1, 2, 3, 4]
}.bind(obj, 1, 2);
func(3, 4);
|
借用其他对象的方法
借用构造函数
借用方法的第一种场景是“借用构造函数”,可以实现类似继承的效果:
|
var A = function(name) {
this.name = name;
}
var B = function() {
A.apply(this, arguments);
}
B.prototype.getName = function() {
return this.name;
}
var b = new B('microzz');
console.log(b.getName()); // microzz
|
类数组
函数参数列表arguments是一个类数组对象,虽然它有下标,但是并不是真正的数组。为了能使用数组的一些方法,我们常常会借用Array.prototype对象上的方法。
比如想往arguments中添加新元素,通常会借用Array.prototype.push
想把arguments转成真正数组的时候,可以借用Array.prototype.slice或者也可以使用ES6的Array.from
About
JavaScript中的call和apply应用的更多相关文章
- Javascript中call函数和apply函数的使用
Javascript 中call函数和apply的使用: Javascript中的call函数和apply函数是对执行上下文进行切换,是将一个函数从当前执行的上下文切换到另一个对象中执行,例如: so ...
- Javascript 中的 call 和 apply
发表于 2012年02月1日 by 愚人码头 原文链接:http://www.css88.com/archives/4431 JavaScript 中通过call或者apply用来代替另一个对象调 ...
- javascript中call函数与apply
javascript中的call方法使当前对象可以调用另一个对象的方法,即改变this的指向内容 var first_object = { num: 42 }; var second_object = ...
- javascript 中caller,callee,call,apply 的概念[转载]
在提到上述的概念之前,首先想说说javascript中函数的隐含参数:arguments Arguments : 该对象代表正在执行的函数和调用它的函数的参数. [function.]argument ...
- 理解和运用javascript中的call及apply
call是为了改变函数上下文context而存在的,换言之,就是改变函数内部this的指向.因为javascript存在[定义时上下文],[运行时上下文]及[上下文]是可以改变的.例如:var fun ...
- javascript 中的call和apply
一.作用及应用场景 call和apply是Function的方法,他的第一个参数是this,第二个是Function的参数.call 和 apply 都是为了改变某个函数运行时的 context 即上 ...
- JavaScript中的call()、apply()与bind():
关于call()与apply(): 在JavaScript中,每个函数都有call与apply(),这两个函数都是用来改变函数体内this的指向,并调用相关的参数. 看一个例子: 定义一个animal ...
- 理解JavaScript中的call和apply方法
call方法 总的来说call()有这几种作用:1.可以借用另一个对象的方法.2.改变this的指向(重要).3.将arguments数组化.下面详细介绍这三种作用: 1.可以借用另一个对象的方法:当 ...
- JavaScript中的call、apply、bind方法的区别
在JavaScript 中,this的指向是动态变化的,很可能在写程序的过程中,无意中破坏掉this的指向,所以我们需要一种可以把this的含义固定的技术,于是就有了call,apply 和bind这 ...
- 简单理解Javascript中的call 和 apply
javascript中面向对像的能力是后来加进来的, 为了兼容性, 所以整出了很多奇特的东西, function Animal(){ this.name = "Animal"; t ...
随机推荐
- AWS 使用总结
A.升配置的流程: 1.新开一台配置较高的机器; 2.将新机器和老机器的磁盘都取消关联,注意需要记录下老机器的磁盘分区设备名,如:/dev/sda1: 3.将老机器的磁盘挂载到新机器上,磁盘分区设备名 ...
- leetcode 之Search in Rotated Sorted Array(三)
描述 Suppose a sorted array is rotated at some pivot unknown to you beforehand. (i.e., 0 1 2 4 5 6 ...
- BeanUtils封装对象时一直提示ClassNotFoundException:org.apache.commons.beanutils.BeanUtils
导包明明正确了,依赖包也全都导对了,还是出错. 困扰了3天. 后来看到这篇博文,https://blog.csdn.net/yanshaoshuai/article/details/81624890 ...
- hdu 1849(巴什博弈)
Rabbit and Grass Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) ...
- pandas 数据结构的基本功能
操作Series和DataFrame中的数据的常用方法: 导入python库: import numpy as np import pandas as pd 测试的数据结构: Series: > ...
- 【PAT】1005. 继续(3n+1)猜想 (25)
1005. 继续(3n+1)猜想 (25) 卡拉兹(Callatz)猜想已经在1001中给出了描述.在这个题目里,情况稍微有些复杂. 当我们验证卡拉兹猜想的时候,为了避免重复计算,可以记录下递推过程中 ...
- python开发学习-day02(元组、字符串、列表、字典深入)
s12-20160109-day02 *:first-child { margin-top: 0 !important; } body>*:last-child { margin-bottom: ...
- Knockout简介
1 Knockout简介 (Introduction) Knockout是一个轻量级的UI类库,通过应用MVVM模式使JavaScript前端UI简单化. Knockout有如下4大重要概念: 声明式 ...
- saltstack系统初始化(九)
一.系统初始化需要的配置 当我们的服务器上架并安装好操作系统后,都会有一些基础的操作,所以生产环境中使用SaltStack,建议将所有服务器都会涉及的基础配置或者软件部署归类放在base环境下.此处, ...
- 【转载】okhttp源码解析
转自:http://www.open-open.com/lib/view/open1472216742720.html https://blog.piasy.com/2016/07/11/Unders ...