详解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 相关文章推荐
js利用数组length属性清空和截短数组的小例子
Jan 15 Javascript
通过js来制作复选框的全选和不选效果
May 22 Javascript
javascript生成随机数方法汇总
Nov 12 Javascript
layui弹出层效果实现代码
May 19 Javascript
深入理解ES6之数据解构的用法
Jan 13 Javascript
通过js动态创建标签,并设置属性方法
Feb 24 Javascript
浅谈Vue响应式(数组变异方法)
May 07 Javascript
CountUp.js数字滚动插件使用方法详解
Oct 17 Javascript
浅谈js中的attributes和Attribute的用法与区别
Jul 16 Javascript
JS倒计时两种实现方式代码实例
Jul 27 Javascript
vue中利用three.js实现全景图的完整示例
Dec 07 Vue.js
详细聊聊浏览器是如何看闭包的
Nov 11 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+DBM的同学录程序(5)
2006/10/09 PHP
PHP下escape解码函数的实现方法
2010/08/08 PHP
php中opendir函数用法实例
2014/11/15 PHP
thinkPHP分页功能实例详解
2017/05/05 PHP
浅谈Laravel核心解读之Console内核
2018/12/02 PHP
javascript下给元素添加事件的方法与代码
2007/08/13 Javascript
多个js与css文件的合并方法详细说明
2012/12/26 Javascript
JavaScript中的条件判断语句使用详解
2015/06/03 Javascript
最新最热最实用的15个jQuery插件汇总
2015/07/05 Javascript
javascript与jquery中的this关键字用法实例分析
2015/12/24 Javascript
angular ng-click防止重复提交实例
2017/06/16 Javascript
jQuery实现可拖动进度条实例代码
2017/06/21 jQuery
vue proxyTable 接口跨域请求调试的示例
2017/09/12 Javascript
看看“疫苗查询”小程序有温度的代码
2018/07/31 Javascript
layui select获取自定义属性方法
2018/08/15 Javascript
原生JS实现前端本地文件上传
2018/09/08 Javascript
详解在vue-cli项目下简单使用mockjs模拟数据
2018/10/19 Javascript
vue+element UI实现树形表格带复选框的示例代码
2019/04/16 Javascript
JS利用prototype给类添加方法操作详解
2019/06/21 Javascript
vue项目打包后提交到git上为什么没有dist这个文件的解决方法
2020/09/16 Javascript
python中常用的九种预处理方法分享
2016/09/11 Python
python GUI库图形界面开发之PyQt5布局控件QHBoxLayout详细使用方法与实例
2020/03/06 Python
python:批量统计xml中各类目标的数量案例
2020/03/10 Python
python3+opencv 使用灰度直方图来判断图片的亮暗操作
2020/06/02 Python
伦敦平价潮流珠宝首饰品牌:Astrid & Miyu
2016/10/10 全球购物
轻松制作精彩视频:Animoto
2018/09/19 全球购物
JSF面试题:Jsf中的核心类用那些?有什么作用?LiftCycle六大生命周期是什么?
2014/07/17 面试题
请解释一下webService? 如何用.net实现webService
2014/06/09 面试题
教师个人自我鉴定
2014/02/08 职场文书
部门年终奖分配方案
2014/05/07 职场文书
协会周年庆活动方案
2014/08/26 职场文书
学习保证书
2015/01/17 职场文书
导游词400字
2015/02/13 职场文书
上市公司财务总监岗位职责
2015/04/03 职场文书
2015年化验员工作总结
2015/04/10 职场文书
Go 自定义package包设置与导入操作
2021/05/06 Golang