详解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搜索同辈元素方法
Feb 10 Javascript
jquery实现无限分级横向导航菜单的方法
Mar 12 Javascript
JavaScript三元运算符的多种使用技巧
Apr 16 Javascript
ES6中非常实用的新特性介绍
Mar 10 Javascript
AngularJS在IE8的不支持的解决方法
May 13 Javascript
借助node实战JSONP跨域实例
Mar 30 Javascript
微信小程序实现多个按钮toggle功能的实例
Jun 13 Javascript
仿淘宝JSsearch搜索下拉深度用法
Jan 15 Javascript
vue 项目打包通过命令修改 vue-router 模式 修改 API 接口前缀
Jun 13 Javascript
微信小程序canvas.drawImage完全显示图片问题的解决
Nov 30 Javascript
使用koa2创建web项目的方法步骤
Mar 12 Javascript
使用Typescript和ES模块发布Node模块的方法
May 25 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创建动态图像
2006/10/09 PHP
利用 window_onload 实现select默认选择
2006/10/09 PHP
PHP session文件独占锁引起阻塞问题解决方法
2015/05/12 PHP
PHP微信支付开发实例
2016/06/22 PHP
文字幻灯片
2006/06/26 Javascript
Prototype中dom对象方法汇总
2008/09/17 Javascript
JS提交并解析后台返回的XML的代码
2008/11/03 Javascript
LazyLoad 延迟加载(按需加载)
2010/05/31 Javascript
jQuery实现仿QQ在线客服效果的滚动层代码
2015/10/15 Javascript
jQuery中的一些小技巧
2017/01/18 Javascript
gulp加批处理(.bat)实现ng多应用一键自动化构建
2017/02/16 Javascript
JavaScript使用readAsDataURL读取图像文件
2017/05/10 Javascript
js实现京东轮播图效果
2017/06/30 Javascript
JS点击动态添加标签、删除指定标签的代码
2018/04/18 Javascript
vue移动端实现下拉刷新
2018/04/22 Javascript
Vue.js点击切换按钮改变内容的实例讲解
2018/08/22 Javascript
vue中当图片地址无效的时候,显示默认图片的方法
2018/09/18 Javascript
node使用async_hooks模块进行请求追踪
2021/01/28 Javascript
Python实现统计文本文件字数的方法
2017/05/05 Python
Python3实现的判断回文链表算法示例
2019/03/08 Python
Python数据结构与算法(几种排序)小结
2019/06/22 Python
django 利用Q对象与F对象进行查询的实现
2020/05/15 Python
Python中无限循环需要什么条件
2020/05/27 Python
python软件测试Jmeter性能测试JDBC Request(结合数据库)的使用详解
2021/01/26 Python
数以千计的折扣工业产品:ESE Direct
2018/05/20 全球购物
神话般的珠宝:Ross-Simons
2020/07/13 全球购物
巴西最大的玩具连锁店:Ri Happy
2020/06/17 全球购物
北美最大的参茸药食商城:德成行
2020/12/06 全球购物
什么是类的返射机制
2016/02/06 面试题
介绍一下OSI七层模型
2012/07/03 面试题
玩具公司的创业计划书
2013/12/31 职场文书
电大奖学金获奖感言
2014/08/14 职场文书
超市七夕促销活动方案
2014/08/28 职场文书
社区党员群众路线教育实践活动心得体会
2014/11/03 职场文书
签约仪式致辞
2015/07/30 职场文书
K8s部署发布Golang应用程序的实现方法
2021/07/16 Golang