详解 JavaScript的 call() 和 apply()
定义
ECMAScript规范为所有函数都包含两个方法(这两个方法非继承而来), call 和 apply 。这两个函数都是在特定的作用域中调用函数,能改变函数的作用域,实际上是改变函数体内 this 的值 。
call 和 apply
| 语法 | 定义 | 说明 |
|---|---|---|
| call(thisObj,Object) | 调用一个对象的一个方法,以另一个对象替换当前对象。 | call 方法可以用来代替另一个对象调用一个方法。call 方法可将一个函数的对象上下文从初始的上下文改变为由 thisObj 指定的新对象.如果没有提供 thisObj 参数,那么 Global 对象被用作 thisObj |
| apply(thisObj,[argArray]) | 应用某一对象的一个方法,用另一个对象替换当前对象。 | 如果 argArray 不是一个有效的数组或者不是 arguments 对象,那么将导致一个 TypeError。如果没有提供 argArray 和 thisObj 任何一个参数,那么 Global 对象将被用作 thisObj, 并且无法被传递任何参数 |
用法
调用函数,传递参数
//定义一个add 方法
function add(x, y) {
return x + y;
}
//用call 来调用 add 方法
function myAddCall(x, y) {
//调用 add 方法 的 call 方法
return add.call(this, x, y);
}
//apply 来调用 add 方法
function myAddApply(x, y) {
//调用 add 方法 的 applly 方法
return add.apply(this, [x, y]);
}
console.log(myAddCall(10, 20)); //输出结果30
console.log(myAddApply(20, 20)); //输出结果40
我们看到通过方法本身的call 和 apply 执行了该函数。
改变函数作用域
var name = '小白';
var obj = {name:'小红'};
function sayName() {
return this.name;
}
console.log(sayName.call(this)); //输出小白
console.log(sayName. call(obj)); //输入小红
我们改变了函数运行的作用域, 通过绑定不同的对象,函数内部 this 也不同。最终输入结果才会这样。
高级用法,实现 js 继承
//父类 Person
function Person() {
this.sayName = function() {
return this.name;
}
}
//子类 Chinese
function Chinese(name) {
//借助 call 实现继承
Person.call(this);
this.name = name;
this.ch = function() {
alert('我是中国人');
}
}
//子类 America
function America(name) {
//借助 call 实现继承
Person.call(this);
this.name = name;
this.am = function() {
alert('我是美国人');
}
}
//测试
var chinese = new Chinese('成龙');
//调用 父类方法
console.log(chinese.sayName()); //输出 成龙
var america = new America('America');
//调用 父类方法
console.log(america.sayName()); //输出 America
区别
- 参数不同, apply 传入的是一个参数数组,也就是将多个参数组合成一个参数数组, call 从第二个参数开始依次传入.
- apply 可以直接将当前函数的arguments对象作为apply的第二个参数传入
结束语
call 和 apply 最大的好处:方便我们解耦,对象不需要和方法有任何的耦合性,能使我们写出更好的面相对象程序。
大家如果看一些 js 框架底层的话会看到好多地方都有大量用到。
详解 JavaScript的 call() 和 apply()的更多相关文章
- 详解javascript中的call, apply
一些学js的同学一看到call, apply, 就蒙了, 感觉不好懂, 看的头大. 今天我们就一起来研究一下这2个东东.彻底弄清楚它们的用法. 定义: call, apply是函数的方法, 只有函数才 ...
- 详解Javascript的继承实现(二)
上文<详解Javascript的继承实现>介绍了一个通用的继承库,基于该库,可以快速构建带继承关系和静态成员的javascript类,好使用也好理解,额外的好处是,如果所有类都用这种库来构 ...
- 【转】详解JavaScript中的this
ref:http://blog.jobbole.com/39305/ 来源:foocoder 详解JavaScript中的this JavaScript中的this总是让人迷惑,应该是js众所周知的坑 ...
- js对象详解(JavaScript对象深度剖析,深度理解js对象)
js对象详解(JavaScript对象深度剖析,深度理解js对象) 这算是酝酿很久的一篇文章了. JavaScript作为一个基于对象(没有类的概念)的语言,从入门到精通到放弃一直会被对象这个问题围绕 ...
- 详解javascript中的this对象
详解javascript中的this对象 前言 Javascript是一门基于对象的动态语言,也就是说,所有东西都是对象,一个很典型的例子就是函数也被视为普通的对象.Javascript可以通过一定的 ...
- 详解JavaScript调用栈、尾递归和手动优化
调用栈(Call Stack) 调用栈(Call Stack)是一个基本的计算机概念,这里引入一个概念:栈帧. 栈帧是指为一个函数调用单独分配的那部分栈空间. 当运行的程序从当前函数调用另外一个函数时 ...
- 详解javascript的类
前言 生活有度,人生添寿. 原文地址:详解javascript的类 博主博客地址:Damonare的个人博客 Javascript从当初的一个"弹窗语言",一步步发展成为现在前后端 ...
- 详解 javascript中offsetleft属性的用法(转)
详解 javascript中offsetleft属性的用法 转载 2015-11-11 投稿:mrr 我要评论 本章节通过代码实例介绍一下offsetleft属性的用法,需要的朋友可以做一 ...
- 详解JavaScript的任务、微任务、队列以及代码执行顺序
摘要: 理解JS的执行顺序. 作者:前端小智 原文:详解JavaScript的任务.微任务.队列以及代码执行顺序 思考下面 JavaScript 代码: console.log("scrip ...
随机推荐
- java中被各种XXUtil/XXUtils辅助类恶心到了,推荐这种命名方法
且看一下有多少个StringUtils 列举一下XXUtil/XXUtils恶劣之处 1. 不知道该用XXUtil还是用XXUtils, 或者XXHelper, XXTool 2. 不知道该用a.ja ...
- 获取html 中的内容 将前台的数据获取到后台
使用js创建一个form表单 ,使用post上传到后台中 下面是代码.在获取html内容的时候使用了js节点来获取内容. parent:父节点.上一级的节点 siblings:兄弟节点.同一级别的节点 ...
- 主机信息收集工具DMitry
主机信息收集工具DMitry DMitry是Kali Linux内置的一款信息收集工具.它的目标主要是Web类主机.它不仅通过主动查询.端口扫描方式,还借助第三方网站和搜索引擎获取信息. 它搜集的 ...
- C#对象序列化与反序列化zz
C#对象序列化与反序列化(转载自:http://www.cnblogs.com/LiZhiW/p/3622365.html) 1. 对象序列化的介绍........................ ...
- 总结30个CSS3选择器(转载)
或许大家平时总是在用的选择器都是:#id .class 以及标签选择器.可是这些还远远不够,为了在开发中更加得心应手,本文总结了30个CSS3选择器,希望对大家有所帮助. 1 *:通用选择器 * ...
- 【SRM】518 Nim
题意 \(K(1 \le K \le 10^9)\)堆石子,每堆石子个数不超过\(L(2 \le 50000)\),问Nim游戏中先手必败局面的数量,答案对\(10^9+7\)取模. 分析 容易得到\ ...
- 从源代码构建 Go 开发环境
从源代码构建 Go 开发环境 Go 1.5 之前的版本 安装C 语言开发环境 在Go 1.5 之前的版本(比如 1.3.1.4),都会部分的依赖 C 语言的工具链,所以如果你有C 语言的开发环境,就可 ...
- goEasy消息推送,pushlet 向特写用户实时推送
goEasy 1先去goEasy官网注册goeasy.io,并创建application,得到superKey 2引入js <script type="text/javascript& ...
- 解决Android界面布局添加EditText组件后界面无法预览
错误报告: Exception raised during rendering: java.lang.System.arraycopy([CI[CII)V Exception details are ...
- linux配置ftp高级权限
建一个用于管理的ftp高级账号,ftproot,定义它的目录,也就是我们存放项目的地址,所属组www, useradd -d /home/www -g www ftproot www里存放很多项目,我 ...