详解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键盘
May 02 Javascript
Jquery进度条插件 Progress Bar小问题解决
Jul 12 Javascript
js实现日期级联效果
Jan 23 Javascript
jquery form表单序列化为对象的示例代码
Mar 05 Javascript
AngularJS基础知识笔记之表格
May 10 Javascript
解读Bootstrap v4 sass设计
May 29 Javascript
selenium 与 chrome 进行qq登录并发邮件操作实例详解
Apr 06 Javascript
jquery实现倒计时小应用
Sep 19 jQuery
简单了解vue中的v-if和v-show的区别
Oct 08 Javascript
vue-resourc发起异步请求的方法
Feb 11 Javascript
vue实现放大镜效果
Sep 17 Javascript
React 条件渲染最佳实践小结(7种)
Sep 27 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 身份验证方面的函数
2009/10/11 PHP
PHP 模拟$_PUT实现代码
2010/03/15 PHP
php下使用iconv需要注意的问题
2010/11/20 PHP
Javascript SHA-1:Secure Hash Algorithm
2006/12/20 Javascript
几行代码轻松搞定jquery实现flash8类似的连接效果
2007/05/03 Javascript
JavaScript中的其他对象
2008/01/16 Javascript
一些主流JS框架中DOMReady事件的实现小结
2011/02/12 Javascript
javascript-简单的计算器实现步骤分解(附图)
2013/05/30 Javascript
js实现拉伸拖动iframe的具体代码
2013/08/03 Javascript
特殊情况下如何获取span里面的值
2014/05/20 Javascript
NodeJS Web应用监听sock文件实例
2015/02/18 NodeJs
jQuery实现瀑布流布局详解(PC和移动端)
2020/09/01 Javascript
vue2.0构建单页应用最佳实战
2017/04/01 Javascript
React Native 集成jpush-react-native的示例代码
2017/08/16 Javascript
深入探讨JavaScript的最基本部分之执行上下文
2019/02/12 Javascript
最简单的vue消息提示全局组件的方法
2019/06/16 Javascript
layui问题之自动滚动二级iframe页面到指定位置的方法
2019/09/18 Javascript
[02:20]DOTA2英雄基础教程 黑暗贤者
2013/12/19 DOTA
Python中struct模块对字节流/二进制流的操作教程
2017/01/21 Python
Python字符串处理实现单词反转
2017/06/14 Python
PyTorch读取Cifar数据集并显示图片的实例讲解
2018/07/27 Python
python实现求特征选择的信息增益
2018/12/18 Python
pyshp创建shp点文件的方法
2018/12/31 Python
pandas 数据索引与选取的实现方法
2019/06/21 Python
浅谈Django2.0 加xadmin踩的坑
2019/11/15 Python
python如何处理程序无法打开
2020/06/16 Python
Python3读写ini配置文件的示例
2020/11/06 Python
HTML5 video 上传预览图片视频如何设置、预览视频某秒的海报帧
2018/08/28 HTML / CSS
Auchan Direct波兰:欧尚在线杂货店
2016/10/19 全球购物
台湾屈臣氏网路商店:Watsons台湾
2020/12/29 全球购物
财务部岗位职责
2013/11/19 职场文书
技校毕业生自荐信
2014/06/03 职场文书
员工试用期自我鉴定范文
2014/09/15 职场文书
优秀教师自我评价范文
2014/09/27 职场文书
寒暑假实习证明书模板
2014/11/29 职场文书
会议简讯范文
2015/07/20 职场文书