详解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对象及属性
Feb 13 Javascript
JS实现简单的Canvas画图实例
Jul 04 Javascript
jQuery设置聚焦并使光标位置在文字最后的实现方法
Aug 02 Javascript
值得分享的Bootstrap Table使用教程
Nov 23 Javascript
微信小程序 开发经验整理
Feb 15 Javascript
浅谈Webpack 是如何加载模块的
May 24 Javascript
Bootstrap Table列宽拖动的方法
Aug 15 Javascript
跨域请求两种方法 jsonp和cors的实现
Nov 11 Javascript
React性能优化系列之减少props改变的实现方法
Jan 17 Javascript
JavaScript随机数的组合问题案例分析
May 16 Javascript
jQuery实现简单弹幕制作
Dec 10 jQuery
原生jQuery实现只显示年份下拉框
Dec 24 jQuery
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
漫威DC即将合作联动,而双方早已经秘密开始
2020/04/09 欧美动漫
PHP类的声明与实例化及构造方法与析构方法详解
2016/01/26 PHP
php解决和避免form表单重复提交的几种方法
2016/08/31 PHP
PHP设计模式之工厂模式实例总结
2017/09/01 PHP
php如何把表单内容提交到数据库
2019/07/08 PHP
phpmyadmin在宝塔面板里进不去的解决方案
2020/07/06 PHP
javascript 当前日期转化为中文的实现代码
2010/05/13 Javascript
javascript中replace( )方法的使用
2015/04/24 Javascript
Jquery动态添加输入框的方法
2015/05/29 Javascript
js查看一个函数的执行时间实例代码
2015/09/12 Javascript
JS加载iFrame出现空白问题的解决办法
2016/05/13 Javascript
JS实现图片剪裁并预览效果
2016/08/12 Javascript
jQuery插件扩展实例【添加回调函数】
2016/11/26 Javascript
vue+axios实现登录拦截的实例代码
2017/05/22 Javascript
vue中element组件样式修改无效的解决方法
2018/02/03 Javascript
详解Vue.js项目API、Router配置拆分实践
2018/03/16 Javascript
js隐式转换的知识实例讲解
2018/09/28 Javascript
JS动画实现回调地狱promise的实例代码详解
2018/11/08 Javascript
js+canvas实现两张图片合并成一张图片的方法
2019/11/01 Javascript
vue 返回上一页,页面样式错乱的解决
2019/11/14 Javascript
jQuery实现颜色打字机的完整代码
2020/03/19 jQuery
python中的__init__ 、__new__、__call__小结
2014/04/25 Python
使用Python的Zato发送AMQP消息的教程
2015/04/16 Python
在Python中操作字符串之replace()方法的使用
2015/05/19 Python
Python切片工具pillow用法示例
2018/03/30 Python
关于Python中的向量相加和numpy中的向量相加效率对比
2019/08/26 Python
Python读取YAML文件过程详解
2019/12/30 Python
Django serializer优化类视图的实现示例
2020/07/16 Python
工厂搬迁方案
2014/05/11 职场文书
工作求职自荐信
2014/06/13 职场文书
校长一岗双责责任书
2015/05/09 职场文书
我的法兰西岁月观后感
2015/06/09 职场文书
导游词之江南周庄
2019/12/06 职场文书
Python连接Postgres/Mysql/Mongo数据库基本操作大全
2021/06/29 Python
一篇文章弄清楚Ajax请求的五个步骤
2022/03/17 Javascript
最新动漫情报:2022年7月新番定档超过30部, OVERLORD骨王第四季也在其中噢
2022/05/04 日漫