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 ...
随机推荐
- Python 库汇总中文版
这又是一个 Awesome XXX 系列的资源整理,由 vinta 发起和维护.内容包括:Web框架.网络爬虫.网络内容提取.模板引擎.数据库.数据可视化.图片处理.文本处理.自然语言处理.机器学习. ...
- go语言入门(三)
条件语句 go语言的条件语句结构如下: go语言的条件语句和其他语言类似.简单列举下: 1.if 语句,布尔表达式不需要括号 if 布尔表达式 { /* 在布尔表达式为 true 时执行 */ } 2 ...
- csu 1548(三分)
1548: Design road Time Limit: 2 Sec Memory Limit: 256 MBSubmit: 383 Solved: 200[Submit][Status][We ...
- java IntelliJ IDEA 13 注册码 IDEA序列号 License Key
java IntelliJ IDEA 13 注册码 IDEA序列号 License Key Username: JavaDeveloper@sskaje.me License: 282971-M1NW ...
- 【PAT】1006. 换个格式输出整数 (15)
1006. 换个格式输出整数 (15) 让我们用字母B来表示“百”.字母S表示“十”,用“12...n”来表示个位数字n(<10),换个格式来输出任一个不超过3位的正整数.例如234应该被输出为 ...
- git与pycharm合并,珠联璧合
前段时间提交代码都是各种手写push push push,好蠢,今天尝试了一下ide直接提交,爽的一匹,做个总结. 首先github帐号肯定要有. 看图,设置好帐号啥的 再设置git路径,这个应该自动 ...
- python开发学习-day06(模块拾忆、面向对象)
s12-20160130-day06 *:first-child { margin-top: 0 !important; } body>*:last-child { margin-bottom: ...
- Ngnix的日志管理和用定时任务完成日志切割
一.日志管理 先来看看ngnix的配置文件的server段 接下来我们解释一下默认格式的具体意思 #log_format main '$remote_addr(远程IP) - $remote_user ...
- Node.js后台开发初体验
Node.js是什么 Node.js是一个Javascript运行环境(runtime),发布于2009年5月,由Ryan Dahl开发,实质时对Chrome V8引擎进行了封装 Node.js安装 ...
- 2017广东工业大学程序设计竞赛决赛--Problem B: 占点游戏
Description 众所周知的是,TMK特别容易迟到,终于在TMK某次又迟到了之后,Maple怒了,Maple大喊一声:"我要跟你决一死战!"然后Maple就跟TMK玩起了一个 ...