详解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 相关文章推荐
在Javascript里访问SharePoint列表数据的实现方法
May 22 Javascript
JavaScript代码复用模式详解
Nov 07 Javascript
JS实现可缩放、拖动、关闭和最小化的浮动窗口完整实例
Mar 04 Javascript
JavaScript排序算法动画演示效果的实现方法
Oct 18 Javascript
AngularJS 仿微信图片手势缩放的实例
Sep 28 Javascript
浅析Javascript中双等号(==)隐性转换机制
Oct 27 Javascript
浅谈webpack打包过程中因为图片的路径导致的问题
Feb 21 Javascript
vue-router权限控制(简单方式)
Oct 29 Javascript
pm2发布node配置文件ecosystem.json详解
May 15 Javascript
详解ES6 export default 和 import语句中的解构赋值
May 28 Javascript
Vue解析剪切板图片并实现发送功能
Feb 04 Javascript
js实现3D旋转相册
Aug 02 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
通过ICQ网关发送手机短信的PHP源程序
2006/10/09 PHP
DISCUZ 论坛管理员密码忘记的解决方法
2009/05/14 PHP
用 Composer构建自己的 PHP 框架之构建路由
2014/10/30 PHP
URL编码转换,escape() encodeURI() encodeURIComponent()
2006/12/27 Javascript
通过length属性判断jquery对象是否存在
2013/10/18 Javascript
Mac OS X 系统下安装和部署Egret引擎开发环境
2014/09/03 Javascript
Javascript数组操作函数总结
2015/02/05 Javascript
原生js和jquery实现图片轮播淡入淡出效果
2015/04/23 Javascript
JavaScript实现的多个图片广告交替显示效果代码
2015/09/04 Javascript
AngularJS中指令的四种基本形式实例分析
2016/11/22 Javascript
JavaScript正则表达式简单实用实例
2017/06/23 Javascript
深入理解JavaScript的值传递和引用传递
2018/10/24 Javascript
Vue中CSS动画原理的实现
2019/02/13 Javascript
jQuery实现简单的Ajax调用功能示例
2019/02/15 jQuery
js作用域和作用域链及预解析
2019/04/11 Javascript
学习LayUI时自研的表单参数校验框架案例分析
2019/07/29 Javascript
Flask框架的学习指南之用户登录管理
2016/11/20 Python
深入理解Python中变量赋值的问题
2017/01/12 Python
python 多维切片之冒号和三个点的用法介绍
2018/04/19 Python
Python操作mongodb数据库进行模糊查询操作示例
2018/06/09 Python
python环形单链表的约瑟夫问题详解
2018/09/27 Python
python networkx 包绘制复杂网络关系图的实现
2019/07/10 Python
解决pyCharm中 module 调用失败的问题
2020/02/12 Python
python使用openpyxl操作excel的方法步骤
2020/05/28 Python
Python三维绘图之Matplotlib库的使用方法
2020/09/20 Python
美国沃尔玛网上超市:Walmart
2020/08/14 全球购物
WebSphere 应用服务器都支持哪些认证
2013/12/26 面试题
应届毕业生个人自我评价
2013/09/20 职场文书
自我推荐书
2013/12/04 职场文书
校园歌手大赛策划书
2014/01/17 职场文书
幼儿园六一儿童节主持节目串词
2014/03/21 职场文书
担保书怎么写
2014/04/01 职场文书
学生会主席演讲稿
2014/04/25 职场文书
人事行政专员岗位职责
2014/07/23 职场文书
故意伤害人身损害赔偿协议书
2014/11/19 职场文书
歌咏比赛口号大全
2015/12/25 职场文书