详解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 实现GridView异步排序、分页的代码
Feb 06 Javascript
js关闭浏览器窗口及检查浏览器关闭事件
Sep 03 Javascript
div模拟选择框示例代码
Nov 03 Javascript
JS创建自定义表格具体实现
Feb 11 Javascript
JS+CSS实现Li列表隔行换色效果的方法
Feb 16 Javascript
jquery实现select下拉框美化特效代码分享
Aug 18 Javascript
简述Matlab中size()函数的用法
Mar 20 Javascript
使用jQuery 操作table 完成单元格合并的实例
Dec 27 jQuery
vue代理和跨域问题的解决
Jul 18 Javascript
微信小程序自定义头部导航栏和导航栏背景图片 navigationStyle问题
Jul 26 Javascript
浅谈laytpl 模板空值显示null的解决方法及简单的js表达式
Sep 19 Javascript
react-intl实现React国际化多语言的方法
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获取随机数组列表的方法
2014/11/13 PHP
php框架CodeIgniter使用redis的方法分析
2018/04/13 PHP
让网页根据不同IE版本显示不同的内容
2009/02/08 Javascript
setTimeout与setInterval在不同浏览器下的差异
2010/01/24 Javascript
火狐4、谷歌12不支持Jquery Validator的解决方法分享
2011/06/20 Javascript
JavaScript闭包 懂不懂由你反正我是懂了
2011/10/21 Javascript
解析javascript 数组以及json元素的添加删除
2013/06/26 Javascript
让JavaScript和其它资源并发下载的方法
2014/10/16 Javascript
jquery中live()方法和bind()方法区别分析
2016/06/23 Javascript
浅谈jquery中使用canvas的问题
2016/10/10 Javascript
JavaScript获取短信验证码(周期性)
2016/12/29 Javascript
JavaScript获取ul中li个数的方法
2017/02/13 Javascript
详解用webpack2.0构建vue2.0超详细精简版
2017/04/05 Javascript
Laravel整合Bootstrap 4的完整方案(推荐)
2018/01/25 Javascript
jQuery中可见性过滤器简单用法示例
2018/03/31 jQuery
解决element UI 自定义传参的问题
2018/08/22 Javascript
bootstrap table插件动态加载表头
2019/07/19 Javascript
vue+elementUI实现简单日历功能
2020/09/24 Javascript
Python Web开发模板引擎优缺点总结
2014/05/06 Python
Python中装饰器学习总结
2018/02/10 Python
python 实现在txt指定行追加文本的方法
2018/04/29 Python
Pandas之排序函数sort_values()的实现
2019/07/09 Python
Python模块 _winreg操作注册表
2020/02/05 Python
Pytest如何使用skip跳过执行测试
2020/08/13 Python
Python 多线程C段扫描、检测 Ping扫描脚本的实现
2020/09/03 Python
Keras保存模型并载入模型继续训练的实现
2021/02/20 Python
CSS3文本换行word-wrap解决英文文本超过固定宽度不换行
2013/10/10 HTML / CSS
CSS3 :default伪类选择器使用简介
2018/03/15 HTML / CSS
Canvas系列之滤镜效果
2019/02/12 HTML / CSS
村官工作鉴定评语
2014/01/27 职场文书
大学同学聚会邀请函
2014/01/29 职场文书
主管会计岗位职责
2014/03/13 职场文书
2014年度安全工作总结
2014/12/04 职场文书
护理心得体会范文
2016/01/22 职场文书
小学美术教学反思
2016/02/17 职场文书
MySQL sql_mode的使用详解
2021/05/08 MySQL