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 ...
随机推荐
- django 项目中的 favicon.ico 处理
django 项目中的 favicon.ico 处理 (django == 2.0.6) 1. 引入模块: from django.views.generic.base import Redirec ...
- nginx解析带中文的url重定向之后404问题
首先,有这样一个需求:一个系统的图片存储是放在upyun上的,现在有个客户需要本地化部署,所以需要将图片进行本地存储.为了兼容,图片存储的路径格式保持和在upyun上的存储路径一致.在upyun上的存 ...
- 结构体对齐及#pragma详细解释
在linux下c语言结构体对齐: 1.自然对齐 struct 是一种复合数据类型,其构成元素既可以是基本数据类型(如int.long.float 等)的变量,也可以是一些复合数据类型(如array.s ...
- linux shell 一些命令
https://stackoverflow.com/questions/918886/how-do-i-split-a-string-on-a-delimiter-in-bash wc: https: ...
- IEEEXtreme 10.0 - Dog Walking
博客中的文章均为 meelo 原创,请务必以链接形式注明 本文地址 Xtreme 10.0 - Dog Walking 题目来源 第10届IEEE极限编程大赛 https://www.hackerra ...
- 第三方登陆微博、qq、微信
源文:http://blog.csdn.net/tivonalh/article/details/60954373 假设是已经申请完成各平台开发者账号. 先来简单的,微博和QQ 微博: 引入微博JS ...
- LoadRunner的Capture Level说明
LoadRunner的Capture Level说明 Capture Level的设置说明: 1.Socket level data. Capture data using trapping on t ...
- poj2362 Square(DFS)
题目链接 http://poj.org/problem?id=2362 题意 输入n根棍子的长度,求这n根棍子是否能组成一个正方形. 思路 假设能组成正方形,则正方形的周长为sum,sum/4为正方形 ...
- JS原生Date类型方法的一些冷知识
ps:由于Date()是js原生函数,不同浏览器的解析器对其实现方式并不同,所以返回值也会有所区别.本文测试未特别申明浏览器的情况下,均是指win7 x64+chrome 44.0.2403.155 ...
- Linq简单使用
简单使用 from子查询 关联多个数据源 分组 let 子句 查询对象(上例中为list变量)为IEnumerable<T>或IQueryable<T>类型 查询返回结果同样为 ...