详解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制作简单弹出层DIV在页面居中 中间显示遮罩的具体方法
Aug 08 Javascript
Javascript验证用户输入URL地址是否为空及格式是否正确
Oct 09 Javascript
jquery.form.js框架实现文件上传功能案例解析(springmvc)
May 26 Javascript
利用JS判断字符串是否含有数字与特殊字符的方法小结
Nov 25 Javascript
JS闭包用法实例分析
Mar 27 Javascript
Element中的Cascader(级联列表)动态加载省\市\区数据的方法
Mar 27 Javascript
vue.js表单验证插件(vee-validate)的使用教程详解
May 23 Javascript
js字符串类型String常用操作实例总结
Jul 05 Javascript
微信小程序全选多选效果实现代码解析
Jan 21 Javascript
JavaScript实现随机点名程序
Mar 25 Javascript
vue内置组件keep-alive事件动态缓存实例
Oct 30 Javascript
JavaScript架构localStorage特殊场景下二次封装操作
Jun 21 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
php5新改动之短标记启用方法
2008/09/11 PHP
ThinkPHP 表单自动验证运用示例
2014/10/13 PHP
thinkphp跨库操作的简单代码实例
2016/09/22 PHP
laravel框架模型中非静态方法也能静态调用的原理分析
2019/11/23 PHP
JS模拟面向对象全解(一、类型及传递)
2011/07/13 Javascript
javascript中apply和call方法的作用及区别说明
2014/02/14 Javascript
jquery实现倒计时代码分享
2014/06/13 Javascript
QQ空间顶部折页撕开效果示例代码
2014/06/15 Javascript
js的image onload事件使用遇到的问题
2014/07/15 Javascript
基于JS实现的笛卡尔乘积之商品发布
2016/05/13 Javascript
第一次接触神奇的Bootstrap菜单和导航
2016/08/01 Javascript
Node.js websocket使用socket.io库实现实时聊天室
2017/02/20 Javascript
VUE-cli3使用 svg-sprite-loader
2018/10/20 Javascript
Vuex 使用 v-model 配合 state的方法
2018/11/13 Javascript
使用koa-log4管理nodeJs日志笔记的使用方法
2018/11/30 NodeJs
详解Bootstrap 学习(一)入门
2019/04/12 Javascript
对node通过fs模块判断文件是否是文件夹的实例讲解
2019/06/10 Javascript
Vue中axios的封装(报错、鉴权、跳转、拦截、提示)
2019/08/20 Javascript
[02:10]三分钟回顾完美世界城市挑战赛
2019/01/24 DOTA
Python中使用支持向量机SVM实践
2017/12/27 Python
浅谈numpy数组中冒号和负号的含义
2018/04/18 Python
Python随机函数库random的使用方法详解
2019/08/21 Python
用Python进行websocket接口测试
2020/10/16 Python
Jupyter Notebook添加代码自动补全功能的实现
2021/01/07 Python
CSS3 优势以及网页设计师如何使用CSS3技术
2009/07/29 HTML / CSS
css3 transform及原生js实现鼠标拖动3D立方体旋转
2016/06/20 HTML / CSS
详解如何通过H5(浏览器/WebView/其他)唤起本地app
2017/12/11 HTML / CSS
俄罗斯宠物用品网上商店:ZooMag
2019/12/12 全球购物
什么是Connection-oriented Protocol/Connectionless Protocol面向连接的协议/无连接协议
2012/09/06 面试题
python+selenium小米商城红米K40手机自动抢购的示例代码
2021/03/24 Python
餐饮企业总经理岗位职责范文
2014/02/18 职场文书
妈妈活动方案
2014/08/15 职场文书
Python list去重且保持原顺序不变的方法
2021/04/03 Python
Go语言空白表示符_的实例用法
2021/07/04 Golang
利用Python将list列表写入文件并读取的方法汇总
2022/03/25 Python
MySQL的prepare使用以及遇到的bug
2022/05/11 MySQL