详解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 相关文章推荐
基于jquery.Jcrop的头像编辑器
Mar 01 Javascript
JavaScript中获取元素索引的函数
Sep 10 Javascript
javascript作用域容易记错的两个地方分析
Jun 22 Javascript
jQuery的attr与prop使用介绍
Oct 10 Javascript
js中arguments,caller,callee,apply的用法小结
Jan 28 Javascript
将HTML的左右尖括号等转义成实体形式的两种实现方式
May 04 Javascript
javascript实现动态模态绑定grid过程代码
Sep 22 Javascript
JavaScript开发人员的10个关键习惯小结
Dec 05 Javascript
Knockoutjs 学习系列(二)花式捆绑
Jun 07 Javascript
react-native-tab-navigator组件的基本使用示例代码
Sep 07 Javascript
webpack+react+antd脚手架优化的方法
Apr 02 Javascript
Bootstrap-table自定义可编辑每页显示记录数
Sep 07 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计算指定目录下文件占用空间的方法
2015/03/13 PHP
PHP页面转UTF-8中文编码乱码的解决办法
2015/10/20 PHP
PHP错误Warning:mysql_query()解决方法
2015/10/24 PHP
twig模板获取全局变量的方法
2016/02/05 PHP
php模拟post上传图片实现代码
2016/06/24 PHP
了解jQuery技巧来提高你的代码
2010/01/08 Javascript
JavaScript学习心得之概述
2015/01/20 Javascript
详细谈谈AngularJS的子级作用域问题
2016/09/05 Javascript
基于jQuery的select下拉框选择触发事件实例分析
2016/11/18 Javascript
vue.js将unix时间戳转换为自定义时间格式
2017/01/03 Javascript
vue2.0实现倒计时的插件(时间戳 刷新 跳转 都不影响)
2017/03/30 Javascript
JS自动生成动态HTML验证码页面
2017/06/14 Javascript
Layui 带多选框表格监听事件以及按钮自动点击写法实例
2019/09/02 Javascript
vue实现将一个数组内的相同数据进行合并
2019/11/07 Javascript
用javascript实现倒计时效果
2021/02/09 Javascript
[00:20]DOTA2荣耀之路7:-ah fu-抢盾
2018/05/31 DOTA
Python开发之Nginx+uWSGI+virtualenv多项目部署教程
2019/05/13 Python
在Python中构建增广矩阵的实现方法
2019/07/01 Python
在python中利用numpy求解多项式以及多项式拟合的方法
2019/07/03 Python
pytorch绘制并显示loss曲线和acc曲线,LeNet5识别图像准确率
2020/01/02 Python
python3中使用__slots__限定实例属性操作分析
2020/02/14 Python
python实现人脸签到系统
2020/04/13 Python
Python脚本实现监听服务器的思路代码详解
2020/05/28 Python
Django contrib auth authenticate函数源码解析
2020/11/12 Python
用 Django 开发一个 Python Web API的方法步骤
2020/12/03 Python
python中time包实例详解
2021/02/02 Python
pycharm 实现调试窗口恢复
2021/02/05 Python
商务助理岗位职责
2013/11/13 职场文书
酒店个人培训自我鉴定
2013/12/11 职场文书
新任教师自我鉴定
2014/02/24 职场文书
意向协议书范本
2014/04/23 职场文书
学习教师敬业奉献模范事迹材料思想汇报
2014/09/19 职场文书
学校副校长四风对照检查材料整改措施
2014/09/25 职场文书
中小学生学籍证明
2014/10/25 职场文书
领导工作表现评语
2015/01/04 职场文书
Mysql数据库中datetime、bigint、timestamp来表示时间选择,谁来存储时间效率最高
2021/08/23 MySQL