Javascript技术难点之apply,call与this之间的衔接


Posted in Javascript onDecember 04, 2015

1.apply定义

apply:调用函数,并用指定对象替换函数的 this 值,同时用指定数组替换函数的参数。

语法:apply([thisObj[,argArray]])

thisObj

可选。要用作 this 对象的对象。

 argArray

可选。要传递到函数的一组参数。

2.call定义

call:调用一个对象的方法,用另一个对象替换当前对象。

语法:call([thisObj[, arg1[, arg2[, [, argN]]]]])

thisObj

可选。将作为当前对象使用的对象。

 arg1, arg2, , argN

可选。将被传递到该方法的参数列表。

3.二者区别

call 的第二个参数可以是任意类型,而apply的第二个参数必须是数组,也可以是arguments。

定义也是有差别的。

4.实例分析

    (1)官方实例:

function callMe(arg1, arg2){
  var s = "";
  s += "this value: " + this;
  s += "<br />";
  for (i in callMe.arguments) {
    s += "arguments: " + callMe.arguments[i];
    s += "<br />";
  }
  return s;
}
document.write("Original function: <br/>");
document.write(callMe(1, 2));
document.write("<br/>");
document.write("Function called with apply: <br/>");
document.write(callMe.apply(3, [ 4, 5 ]));
document.write(callMe.call(3, 4, 5 ));
// Output: // Original function: // this value: [object Window] // arguments: 1 // arguments: 2 // Function called with apply: // this value: 3 // arguments: 4 // arguments: 5

 第一个用apply的:定义:调用函数,并用指定对象替换函数的 this 值 调用函数callMe,使用指定的对象3替换callMe函数中的this,这时候这里的this就从之前的[object Window]变成了3。 第一个用call的:定义:调用一个对象的方法,用另一个对象替换当前对象。 调用对象callMe的方法,用另一个对象3替换callMe中的对象。 从这些结果分析中可以看出,这两者都是使用指定的对象中的对象或者指定的值改变了对象中的this。 也可以说:是一个函数中的对象(this)"劫持"了另一个要执行函数中的对象(this)。 其实这里引出了一个问题:this到底是啥?为何如此重要的一次次来费劲心思的来改变它的指向? 传送门:javascript技术难点(三)之this、new、apply和call详解(这里面说的很棒,绝对够你喝一壶)     (2)实例:

function zqz(a,b){
  return alert(a+b);
}
function zqz_1(a,b){
  zqz.apply(zqz_1,[a,b])
}
zqz_1(1,2)  //->3

分析:根据定义:调用函数,并用指定对象替换函数的 this 值,

这里调用函数zqz,并用指定的对象zqz_1替换zqz函数的this值。

要注意js中的函数名其实是对象,因为函数名是对Funtion对象的引用!

function add(a, b)
{
 alert(a + b);
}
function sub(a, b)
{
 alert(a - b);
}
add.call(sub, 3, 1); // 4

分析:根据定义:调用一个对象的方法,用另一个对象替换当前对象。

这里就是调用对象add的方法,并用add对象替换当前对象sub;

再来一个例子:

function zqz(a,b){
  this.name=a;
  this.age=b;
  alert(this.name+" "+this.age);
}
function zqz_1(a,b){
  zqz.apply(this,[a,b])   //我们亦可以这么写  zqz.apply(this,arguments) 
}
zqz_1("Nic",12)  //Nic 12

分析:根据定义:调用函数,并用指定对象替换函数的 this 值,

这里调用函数zqz,使用指定的对象this替换函数zqz的this。

再来一个例子:

<input type="text" id="myText"  value="input text">
function Obj(){
  this.value="对象!";
}
var value="global 变量";
function Fun1(){
  alert(this.value);
}
Fun1();  //global 变量
Fun1.call(window); //global 变量
Fun1.call(document.getElementById('myText')); //input text
Fun1.call(new Obj());  //对象!
Fun1(); //global 变量

分析:定义:调用一个对象的方法,用另一个对象替换当前对象。

调用Fun1对象的方法,用window对象替换当前Fun1中的对象。

调用Fun1对象的方法,用input中对象替换当前Fun1中的对象。

调用Fun1对象的方法,用新new出来的obj中的对象替换当前Fun1中的对象。

最后再总结一下:

如果在javascript语言里没有通过new(包括对象字面量定义)、call和apply改变函数的this指针,函数的this指针都是指向window的。

ps:apply的其他巧妙用法:

大家会不会觉得既然apply和call的用法差不多,那么为什么还同时存在这两种方法呢?完全可以丢掉一个呀。后来才发现一篇文章中讲到apply因为它所传参数为数组这一特点还有许多其他的妙用。

a) Math.max 可以实现得到数组中最大的一项:

因为Math.max 参数里面不支持Math.max([param1,param2]) 也就是数组,但是它支持Math.max(param1,param2,param3…),所以可以根据apply的特点来解决 var max=Math.max.apply(null,array),这样轻易的可以得到一个数组中最大的一项。(apply会将一个数组转换为一个参数接一个参数的传递给方法)

这块在调用的时候第一个参数给了一个null,这个是因为没有对象去调用这个方法,只需要用这个方法帮助运算,得到返回的结果就行,所以直接传递了一个null过去。

b) Math.min  可以实现得到数组中最小的一项:

同样和 max是一个思想 var min=Math.min.apply(null,array)。

c) 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);

也可以这样理解,arr1调用了push方法,参数是通过apply将数组装换为参数列表的集合。

d) 小结:通常在什么情况下,可以使用apply类似Math.min等之类的特殊用法:

一般在目标函数只需要n个参数列表,而不接收一个数组的形式([param1[,param2[,…[,paramN]]]]),可以通过apply的方式巧妙地解决这个问题。

Javascript 相关文章推荐
基于jquery ajax 用户无刷新登录方法详解
Apr 28 Javascript
jquery点击页面任何区域实现鼠标焦点十字效果
Jun 21 Javascript
Javascript设计模式之观察者模式的多个实现版本实例
Mar 03 Javascript
javascript中一些util方法汇总
Jun 10 Javascript
详解Javascript模板引擎mustache.js
Jan 20 Javascript
js HTML5多图片上传及预览实例解析(不含前端的文件分割)
Aug 26 Javascript
web 前端常用组件之Layer弹出层组件
Sep 22 Javascript
清除js缓存的多种方法总结
Dec 09 Javascript
ligerUI---ListBox(列表框可移动的实例)
Nov 28 Javascript
vue全局组件与局部组件使用方法详解
Mar 29 Javascript
vue-awesome-swiper 基于vue实现h5滑动翻页效果【推荐】
Nov 08 Javascript
基于javascript canvas实现五子棋游戏
Jul 08 Javascript
给before和after伪元素设置js效果的方法
Dec 04 #Javascript
全面解析Bootstrap手风琴效果
Apr 17 #Javascript
简单对比分析JavaScript中的apply,call与this的使用
Dec 04 #Javascript
详解JavaScript的Date对象(制作简易钟表)
Apr 07 #Javascript
浅析2种JavaScript继承方式
Dec 04 #Javascript
详解jQuery移动页面开发中的ui-grid网格布局使用
Dec 03 #Javascript
浅析jQuery Mobile的初始化事件
Dec 03 #Javascript
You might like
PHP验证码类代码( 最新修改,完全定制化! )
2010/12/02 PHP
用PHP实现 上一篇、下一篇的代码
2012/09/29 PHP
PHP图片加水印实现方法
2016/05/06 PHP
PHP微信网页授权的配置文件操作分析
2019/05/29 PHP
PHP哈希表实现算法原理解析
2020/12/11 PHP
IE与Firefox在JavaScript上的7个不同写法小结
2009/09/14 Javascript
js获得鼠标的坐标值的方法
2013/03/13 Javascript
利用a标签自动解析URL分析网址实例
2014/10/20 Javascript
iscroll.js的上拉下拉刷新时无法回弹的解决方法
2016/02/18 Javascript
js获取元素的外链样式的简单实现方法
2016/06/06 Javascript
jquery dataTable 后台加载数据并分页实例代码
2017/06/07 jQuery
JS判断字符串是否为整数的方法--简单的正则判断
2018/07/23 Javascript
详解Vue中使用插槽(slot)、聚类插槽
2019/04/12 Javascript
vue使用混入定义全局变量、函数、筛选器的实例代码
2019/07/29 Javascript
Vue.js暴露方法给WebView的使用操作
2020/09/07 Javascript
python处理图片之PIL模块简单使用方法
2015/05/11 Python
Pycharm设置界面全黑的方法
2018/05/23 Python
python matplotlib绘图,修改坐标轴刻度为文字的实例
2018/05/25 Python
解决tensorflow模型参数保存和加载的问题
2018/07/26 Python
Scrapy使用的基本流程与实例讲解
2018/10/21 Python
Python判断一个list中是否包含另一个list全部元素的方法分析
2018/12/24 Python
Python生命游戏实现原理及过程解析(附源代码)
2019/08/01 Python
django 控制页面跳转的例子
2019/08/06 Python
python聚类算法解决方案(rest接口/mpp数据库/json数据/下载图片及数据)
2019/08/28 Python
python银行系统实现源码
2019/10/25 Python
Python使用Socket实现简单聊天程序
2020/02/28 Python
PyQt5 如何让界面和逻辑分离的方法
2020/03/24 Python
使用pandas实现筛选出指定列值所对应的行
2020/12/13 Python
python中os.remove()用法及注意事项
2021/01/31 Python
美国Lolё官网:购买大胆而美丽的女性运动服装
2017/05/22 全球购物
小学教师岗位职责
2013/11/25 职场文书
玩具公司的创业计划书
2013/12/31 职场文书
大学生工作自荐书
2014/06/16 职场文书
2014年节能减排工作总结
2014/12/06 职场文书
单位综合评价意见
2015/06/05 职场文书
Go gorilla/sessions库安装使用
2022/08/14 Golang