详解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 相关文章推荐
从新浪弄下来的全屏广告代码 与使用说明
Mar 15 Javascript
尝试在让script的type属性等于text/html
Jan 15 Javascript
js批量设置样式的三种方法不推荐使用with
Feb 25 Javascript
一步一步封装自己的HtmlHelper组件BootstrapHelper(二)
Sep 14 Javascript
JS实现颜色的10进制转化成rgba格式的方法
Sep 04 Javascript
Angular 4.0学习教程之架构详解
Sep 12 Javascript
VUE前端cookie简单操作
Oct 17 Javascript
vue绑定的点击事件阻止冒泡的实例
Feb 08 Javascript
JS实现数组去重,显示重复元素及个数的方法示例
Jan 21 Javascript
详解JS实现简单的时分秒倒计时代码
Apr 25 Javascript
VUE写一个简单的表格实例
Aug 06 Javascript
深入理解 TypeScript Reflect Metadata
Dec 12 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 年月日的三级联动实例代码
2017/05/24 PHP
Prototype 1.5.0_rc1 及 Prototype 1.5.0 Pre0小抄本
2006/09/22 Javascript
Prototype使用指南之form.js
2007/01/10 Javascript
javascript中文本框中输入法切换的问题
2013/12/10 Javascript
window.open打开页面居中显示的示例代码
2013/12/27 Javascript
node.js中使用node-schedule实现定时任务实例
2014/06/03 Javascript
Node.js编写组件的三种实现方式
2016/02/25 Javascript
一道关于JavaScript变量作用域的面试题
2016/03/08 Javascript
iScroll.js 使用方法参考
2016/05/16 Javascript
bootstrap手风琴折叠示例代码分享
2017/05/22 Javascript
JavaScript中使用Async实现异步控制
2017/08/15 Javascript
详解React Native顶|底部导航使用小技巧
2017/09/14 Javascript
javascript 作用于作用域链的详解
2017/09/27 Javascript
vue中echarts3.0自适应的方法
2018/02/26 Javascript
浅谈Node 异步IO和事件循环
2019/05/05 Javascript
详解在React-Native中持久化redux数据
2019/05/22 Javascript
Node.js之删除文件夹(含递归删除)代码实例
2019/09/09 Javascript
微信小程序实现侧边栏分类
2019/10/21 Javascript
javascript跳转与返回和刷新页面的实例代码
2019/11/20 Javascript
VUE和Antv G6实现在线拓扑图编辑操作
2020/10/28 Javascript
原生JS实现拖拽功能
2020/12/16 Javascript
[41:05]Serenity vs Pain 2018国际邀请赛小组赛BO2 第二场 8.19
2018/08/21 DOTA
详解python并发获取snmp信息及性能测试
2017/03/27 Python
python模拟表单提交登录图书馆
2018/04/27 Python
使用PyTorch将文件夹下的图片分为训练集和验证集实例
2020/01/08 Python
windows下python安装pip方法详解
2020/02/10 Python
python加密解密库cryptography使用openSSL生成的密匙加密解密
2020/02/11 Python
html5+css3进度条倒计时动画特效代码【推荐】
2016/03/08 HTML / CSS
Born鞋子官网:Born Shoes
2017/04/06 全球购物
纽约手袋品牌:KARA
2018/03/18 全球购物
CLR与IL分别是什么含义
2016/08/23 面试题
基层党员公开承诺书
2014/05/29 职场文书
学生实习证明范文
2014/09/28 职场文书
2014年十八届四中全会思想汇报范文
2014/10/17 职场文书
烛光里的微笑观后感
2015/06/17 职场文书
2016年感恩教师节活动总结
2016/04/01 职场文书