详解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代码
Nov 04 Javascript
js hover 定时器(实例代码)
Nov 12 Javascript
jquery ajax对特殊字符进行转义防止js注入使用示例
Nov 21 Javascript
快速解决FusionCharts联动的中文乱码问题
Dec 04 Javascript
JS与jQ读取xml文件的方法
Dec 08 Javascript
Swiper实现轮播图效果
Jul 03 Javascript
js使用html2canvas实现屏幕截取的示例代码
Aug 28 Javascript
详解Javascript 中的 class、构造函数、工厂函数
Dec 20 Javascript
JS简单获得节点元素的方法示例
Feb 10 Javascript
VUE基于NUXT的SSR 服务端渲染
Nov 30 Javascript
javascript使用链接跨域下载图片
Nov 01 Javascript
node.js开发辅助工具nodemon安装与配置详解
Feb 06 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缩放图片(根据宽高的等比例缩放)实例介绍
2013/06/09 PHP
php图片添加文字水印实现代码
2016/03/15 PHP
php微信公众号开发(3)php实现简单微信文本通讯
2016/12/15 PHP
图片上传即时显示缩略图的js代码
2009/05/27 Javascript
javascript学习笔记(十四) window对象使用介绍
2012/06/20 Javascript
精心挑选的15款优秀jQuery 本特效插件和教程
2012/08/06 Javascript
利用JS解决ie6不支持max-width,max-height问题的方法
2014/01/02 Javascript
jQuery照片伸缩效果不影响其他元素的布局
2014/05/09 Javascript
JavaScript Math.ceil 方法(对数值向上取整)
2015/01/09 Javascript
基于JavaScript创建动态Dom
2015/12/08 Javascript
基于jquery实现表格无刷新分页
2016/01/07 Javascript
JS实现移动端按首字母检索城市列表附源码下载
2017/07/05 Javascript
js实现从左向右滑动式轮播图效果
2017/07/07 Javascript
BootStrap模态框不垂直居中的解决方法
2017/10/19 Javascript
Vue服务器渲染Nuxt学习笔记
2018/01/31 Javascript
微信小程序实现文字跑马灯
2020/05/26 Javascript
JS实现判断数组是否包含某个元素示例
2019/05/24 Javascript
vue项目中使用bpmn-自定义platter的示例代码
2020/05/11 Javascript
以一段代码为实例快速入门Python2.7
2015/03/31 Python
R vs. Python 数据分析中谁与争锋?
2017/10/18 Python
python读取几个G的csv文件方法
2019/01/07 Python
简单了解Python3里的一些新特性
2019/07/13 Python
python异常处理和日志处理方式
2019/12/24 Python
Python通过正则库爬取淘宝商品信息代码实例
2020/03/02 Python
CSS3正方体旋转示例代码
2013/08/08 HTML / CSS
DVF官方网站:美国时装界尊尚品牌
2017/08/29 全球购物
英国山地公路自行车商店:Tweeks Cycles
2018/03/16 全球购物
美容师的职业规划书
2013/12/27 职场文书
高二地理教学反思
2014/01/24 职场文书
中秋节超市促销方案
2014/01/30 职场文书
大学学习个人的自我评价
2014/02/18 职场文书
《池塘边的叫声》教学反思
2014/04/12 职场文书
护理专业自荐书
2014/06/04 职场文书
材料成型及控制工程专业求职信
2014/06/19 职场文书
机关党员三严三实心得体会
2014/10/13 职场文书
学生保证书格式
2015/02/27 职场文书