详解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继承机制的设计思想分享
Aug 28 Javascript
jquery 卷帘效果实现代码(不同方向)
Feb 05 Javascript
代码获取历史上的今天发生的事
Apr 11 Javascript
浅谈JavaScript实现面向对象中的类
Dec 09 Javascript
jQuery插件AjaxFileUpload实现ajax文件上传
May 05 Javascript
Bootstrap教程JS插件弹出框学习笔记分享
May 17 Javascript
浅谈angularJS中的事件
Jul 12 Javascript
vue实现列表的添加点击
Dec 29 Javascript
基于jQuery实现的单行公告活动轮播效果
Aug 23 jQuery
Vue 中使用 CSS Modules优雅方法
Apr 09 Javascript
vue 解决addRoutes动态添加路由后刷新失效问题
Jul 02 Javascript
element-ui 中的table的列隐藏问题解决
Aug 24 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
再Docker中架设完整的WordPress站点全攻略
2015/07/29 PHP
微信公众号开发之获取位置信息php代码
2018/06/13 PHP
thinkphp5实现微信扫码支付
2019/12/23 PHP
用jquery统计子菜单的条数示例代码
2013/10/18 Javascript
Javascript基础教程之数组 array
2015/01/18 Javascript
详解AngularJS中的表达式使用
2015/06/16 Javascript
JS实现很实用的对联广告代码(可自适应高度)
2015/09/18 Javascript
jQuery回到顶部的代码
2016/07/09 Javascript
详解React native全局变量的使用(跨组件的通信)
2017/09/07 Javascript
JavaScript 中的 this 工作原理
2018/06/20 Javascript
vuex实现及简略解析(小结)
2019/03/01 Javascript
JS实现处理时间,年月日,星期的公共方法示例
2019/05/31 Javascript
微信小程序使用echarts获取数据并生成折线图
2019/10/16 Javascript
深入解读VUE中的异步渲染的实现
2020/06/19 Javascript
解决VUE自定义拖拽指令时 onmouseup 与 click事件冲突问题
2020/07/24 Javascript
springboot+vue+对接支付宝接口+二维码扫描支付功能(沙箱环境)
2020/10/15 Javascript
python开发之thread线程基础实例入门
2015/11/11 Python
Python爬取十篇新闻统计TF-IDF
2018/01/03 Python
python读取csv文件并把文件放入一个list中的实例讲解
2018/04/27 Python
python3中zip()函数使用详解
2018/06/29 Python
python中join()方法介绍
2018/10/11 Python
浅谈Scrapy网络爬虫框架的工作原理和数据采集
2019/02/07 Python
Python进阶之@property动态属性的实现
2019/04/01 Python
如何基于windows实现python定时爬虫
2020/05/01 Python
python 读取.nii格式图像实例
2020/07/01 Python
让IE6支持css3,让 IE7、IE8 都支持CSS3
2011/10/09 HTML / CSS
德国体育用品网上商店:SC24.com
2016/08/01 全球购物
英国排名第一的在线宠物用品商店:Monster Pet Supplies
2018/05/20 全球购物
卡西欧B级产品官方网站:Casio Outlet
2018/05/22 全球购物
说出ArrayList,Vector, LinkedList的存储性能和特性
2015/01/04 面试题
经典C++面试题一
2016/11/06 面试题
机电工程学生自荐信范文
2013/12/07 职场文书
导游词之镇江焦山
2019/11/21 职场文书
Pandas数据类型之category的用法
2021/06/28 Python
jdbc中自带MySQL 连接池实践示例
2022/07/23 MySQL
使用JS前端技术实现静态图片局部流动效果
2022/08/05 Javascript