详解js中的apply与call的用法


Posted in Javascript onJuly 30, 2016

前言

call 和 apply 都是为了改变某个函数运行时的 context 即上下文而存在的,换句话说,就是为了改变函数体内部 this 的指向
call 和 apply二者的作用完全一样,只是接受参数的方式不太一样。

方法定义
apply
Function.apply(obj,args)方法能接收两个参数:

obj:这个对象将代替Function类里this对象

args:这个是数组或类数组,apply方法把这个集合中的元素作为参数传递给被调用的函数。

call

call方法apply方法的第一个参数是一样的,只不过第二个参数是一个参数列表

在非严格模式下当我们第一个参数传递为null或undefined时,函数体内的this会指向默认的宿主对象,在浏览器中则是window

var test = function(){
  console.log(this===window);
}
test.apply(null);//true
test.call(undefined);//true

用法

"劫持"别人的方法

此时foo中的logName方法将被bar引用 ,this指向了bar

var foo = {
  name:"mingming",
  logName:function(){
    console.log(this.name);
  }
}
var bar={
  name:"xiaowang"
};
foo.logName.call(bar);//xiaowang

实现继承

function Animal(name){   
  this.name = name;   
  this.showName = function(){   
    console.log(this.name);   
  }   
}   

function Cat(name){  
  Animal.call(this, name);  
}   

var cat = new Cat("Black Cat");   
cat.showName(); //Black Cat

在实际开发中,经常会遇到this指向被不经意改变的场景。
有一个局部的fun方法,fun被作为普通函数调用时,fun内部的this指向了window,但我们往往是想让它指向该#test节点,见如下代码:

window.id="window";
document.querySelector('#test').onclick = function(){
  console.log(this.id);//test
  var fun = function(){
    console.log(this.id);
  }
  fun();//window
}

使用call,apply我们就可以轻松的解决这种问题了

window.id="window";
document.querySelector('#test').onclick = function(){
  console.log(this.id);//test
  var fun = function(){
    console.log(this.id);
  }
  fun.call(this);//test
}

当然你也可以这样做,不过在ECMAScript 5strict模式下,这种情况下的this已经被规定为不会指向全局对象,而是undefined:

window.id="window";
document.querySelector('#test').onclick = function(){
  var that = this;
  console.log(this.id);//test
  var fun = function(){
    console.log(that.id);
  }
  fun();//test
}
function func(){
  "use strict"
  alert ( this );  // 输出:undefined
}
func();

其他用法

类数组

这里把符合以下条件的对象称为类数组

1.具有length属性

2.按索引方式存储数据

3.不具有数组的push,pop等方法

常见类数组有 arguments,NodeList!

(function(){
  Array.prototype.push.call(arguments,4);
  console.log(arguments);//[1, 2, 3, 4]
})(1,2,3)

这样就往arguments中push一个4进去了

Array.prototype.push 页可以实现两个数组合并

同样push方法没有提供push一个数组,但是它提供了push(param1,param,…paramN) 所以同样也可以通过apply来装换一下这个数组,即:

var arr1=new Array("1","2","3"); 
var arr2=new Array("4","5","6"); 
Array.prototype.push.apply(arr1,arr2); 
console.log(arr1);//["1", "2", "3", "4", "5", "6"]

也可以这样理解,arr1调用了push方法,参数是通过apply将数组装换为参数列表的集合.

再比如我想求类数组中的最大值

(function(){
  var maxNum = Math.max.apply(null,arguments);
  console.log(maxNum);//56
})(34,2,56);

判断类型

console.log(Object.prototype.toString.call(123)) //[object Number]
console.log(Object.prototype.toString.call('123')) //[object String]
console.log(Object.prototype.toString.call(undefined)) //[object Undefined]
console.log(Object.prototype.toString.call(true)) //[object Boolean]
console.log(Object.prototype.toString.call({})) //[object Object]
console.log(Object.prototype.toString.call([])) //[object Array]
console.log(Object.prototype.toString.call(function(){})) //[object Function]

以上就是apply与call的用法总结的全部内容,欢迎大家积极留言参加讨论,也希望本文对大家学习javascript有所帮助。

Javascript 相关文章推荐
Prototype源码浅析 String部分(二)
Jan 16 Javascript
javascript获取设置div的高度和宽度兼容任何浏览器
Sep 22 Javascript
js与jquery回车提交的方法
Feb 03 Javascript
用JS生成UUID的方法实例
Mar 30 Javascript
AngularJS入门(用ng-repeat指令实现循环输出
May 05 Javascript
关于vue.js弹窗组件的知识点总结
Sep 11 Javascript
jQuery的ajax中使用FormData实现页面无刷新上传功能
Jan 16 Javascript
jquery实现下拉框左右选择功能
Feb 21 Javascript
jQuery操作之效果详解
May 19 jQuery
web前端vue实现插值文本和输出原始html
Jan 19 Javascript
jQuery位置选择器用法实例分析
Jun 28 jQuery
如何在Vue中使localStorage具有响应式(思想实验)
Jul 14 Javascript
javascript回到顶部特效
Jul 30 #Javascript
javascript鼠标滑过显示二级菜单特效
Nov 18 #Javascript
避免jQuery名字冲突 noConflict()方法
Jul 30 #Javascript
分享jQuery封装好的一些常用操作
Jul 28 #Javascript
一个仿微博登陆邮箱提示框js开发案例
Jul 28 #Javascript
利用JS实现数字增长
Jul 28 #Javascript
灵活使用数组制作图片切换js实现
Jul 28 #Javascript
You might like
编写PHP脚本使WordPress的主题支持Widget侧边栏
2015/12/14 PHP
php连接mysql数据库
2017/03/21 PHP
如何直接访问php实例对象中的private属性详解
2017/10/12 PHP
用javascript操作xml
2006/11/04 Javascript
jquery keypress,keyup,onpropertychange键盘事件
2010/06/25 Javascript
iframe的onload在Chrome/Opera中执行两次Bug的解决方法
2011/03/17 Javascript
zeroclipboard 单个复制按钮和多个复制按钮的实现方法
2014/06/14 Javascript
JavaScript实现判断图片是否加载完成的3种方法整理
2015/03/13 Javascript
javascript实现简单的全选和反选功能
2016/01/05 Javascript
快速掌握Node.js事件驱动模型
2016/03/21 Javascript
JavaScript原生编写《飞机大战坦克》游戏完整实例
2017/01/04 Javascript
JavaScript基础之this详解
2017/06/04 Javascript
JavaScript条件判断_动力节点Java学院整理
2017/06/26 Javascript
JS分页的实现(同步与异步)
2017/09/16 Javascript
JS简单实现点击跳转登陆邮箱功能的方法
2017/10/31 Javascript
js实时监控文本框输入字数的实例代码
2018/01/18 Javascript
vuejs 切换导航条高亮(路由菜单高亮)的方法示例
2018/05/29 Javascript
解决微信小程序调用moveToLocation失效问题【超简单】
2019/04/12 Javascript
了解javascript中的Dom操作
2019/05/27 Javascript
[35:44]2014 DOTA2华西杯精英邀请赛 5 24 iG VS VG
2014/05/26 DOTA
一些Python中的二维数组的操作方法
2015/05/02 Python
python字典多键值及重复键值的使用方法(详解)
2016/10/31 Python
PyQt 线程类 QThread使用详解
2017/07/16 Python
python递归函数绘制分形树的方法
2018/06/22 Python
python 移除字符串尾部的数字方法
2018/07/17 Python
python 实现矩阵上下/左右翻转,转置的示例
2019/01/23 Python
HTML5中原生的右键菜单创建方法
2016/06/28 HTML / CSS
Html5之自定义属性(data-,dataset)
2019/11/19 HTML / CSS
玩具反斗城西班牙网上商城:ToysRUs西班牙
2017/01/19 全球购物
什么是属性访问器
2015/10/26 面试题
软件测试企业面试试卷
2016/07/13 面试题
管理学院毕业生自荐信范文
2014/03/10 职场文书
养牛场项目建议书
2014/05/13 职场文书
技术经济专业求职信
2014/09/03 职场文书
教师党员自我评价范文
2015/03/04 职场文书
如何解决goland,idea全局搜索快捷键失效问题
2022/04/03 Golang