改变this指向

要先明白存在call和apply的原因,才能记得牢一点:

在javascript OOP中,我们经常会这样定义:

function cat(){
}
cat.prototype={
  food:"fish",
  say: function(){
    alert("I love "+this.food);
  }
}
var blackCat = new cat;
blackCat.say();
但是如果我们有一个对象whiteDog = {food:"bone"},我们不想对它重新定义say方法,那么我们可以通过call或apply用blackCat的say方法:blackCat.say.call(whiteDog);

所以,可以看出call和apply是为了动态改变this而出现的,当一个object没有某个方法,但是其他的有,我们可以借助call或apply用其它对象的方法来操作。

用的比较多的,通过document.getElementsByTagName选择的dom 节点是一种类似array的array。它不能应用Array下的push,pop等方法。我们可以通过:
var domNodes = Array.prototype.slice.call(document.getElementsByTagName("*"));
这样domNodes就可以应用Array下的所有方法了。

对arguments对象使用Array.prototype.slice()方法,可以将其转化为数组。

采用同样的办法,也可以将NodeList对象转化为数组。看下面的例子:
//在IE8及之前无效
var arryOfNodes = Array.prototype.slice.call(someNode.childNodes, 0);
在IE8及之前版本,将NodeList实现为一个COM对象,要想在IE中将NodeList转换为数组,必须手动枚举所有成员。
function convertToArray(nodes) {
var array = null;
try {
array = Array.prototype.slice.call(nodes, 0);
} catch (ex) {
array = [];
for(var i=0, l=nodes.length; i < l; i++){
array.push(nodes[i]);
}
}
}

call 和 apply 都是为了改变某个函数运行时的 context 即上下文而存在的,换句话说,就是为了改变函数体内部 this 的指向。因为 JavaScript 的函数存在「定义时上下文」和「运行时上下文」以及「上下文是可以改变的」这样的概念。

二者的作用完全一样,只是接受参数的方式不太一样。例如,有一个函数 func1 定义如下:

var func1 = function(arg1, arg2) {};

就可以通过 func1.call(this, arg1, arg2); 或者 func1.apply(this, [arg1, arg2]); 来调用。其中 this 是你想指定的上下文,他可以任何一个 JavaScript 对象(JavaScript 中一切皆对象),call 需要把参数按顺序传递进去,而 apply 则是把参数放在数组里。

JavaScript 中,某个函数的参数数量是不固定的,因此要说适用条件的话,当你的参数是明确知道数量时,用 call,而不确定的时候,用 apply,然后把参数 push 进数组传递进去。当参数数量不确定时,函数内部也可以通过 arguments 这个数组来便利所有的参数。

 

Function.prototype.bind

var obj = {
name: "salody"
};
var func = function (a, b, c, d) {
console.log(this.name); //输出salody
console.log([a, b, c, d]); //输出 [1, 2, 6, 7]
}.bind(obj, 1, 2); func(6, 7, 8, 9); //实际上这里的8,9是多余出来的实参。 Function.prototype.bind = function () {
var self = this, //保存原函数
context = Array.prototype.shift.call(arguments), //需要绑定的this上下文
args = Array.prototype.slice.call(arguments); //剩余的参数转化成数组
return function () {
return self.apply(context, [].concat.call(args, [].slice.call(arguments)));
//执行新的函数时,会把之前传入的context当做新函数的this
//并且组合两次分别传入的参数,作为新函数的参数
}
}

  

如何理解和熟练运用js中的call及apply?的更多相关文章

  1. 理解和熟练运用js中的call及apply

    call 和 apply 都是为了改变某个函数运行时的 context 即上下文而存在的,换句话说,就是为了改变函数体内部 this 的指向. 因为 JavaScript 的函数存在「定义时上下文」和 ...

  2. 如何理解和熟练使用JS 中的call apply

    有时候看一两个关于apply或call的小例子,感觉能够理解一点点但是下次碰到又要纠结半天才能转过弯来-而且不知道怎么应用到实际工作当中去- call 和 apply 都是为了改变某个函数运行时的 c ...

  3. js笔记——理解js中的call及apply

    call及apply在js里经常碰得到,但一直感觉很陌生,不能熟练使用.怎样才能熟练应用呢? 为什么存在call和apply? 在javascript OOP中,我们经常会这样定义: function ...

  4. 关于 js 中的 call 和 apply使用理解

    关于 js 中的 call 和 apply使用理解 在学习新的东西时候,碰到以前看过而又不理解,或则记忆不深的地方不妨回头看看书里知识点,有助于加深理解.正所谓--温故而知新. 废话不多说,直接上代码 ...

  5. 快速理解js中的call,apply的作用

    今天被人问到js中的call,apply的区别和用途,解释了一番后,想到之前在逼乎上看到一位小伙伴生动形象的解释 本身不难理解,看下MDN就知道了,但是不常用,遇到了,还要脑回路回转下.或者时间长了, ...

  6. JS中的call、apply、bind方法

    JS中的call.apply.bind方法 一.call()和apply()方法 1.方法定义 call方法: 语法:call([thisObj[,arg1[, arg2[,   [,.argN]]] ...

  7. JS中的call()和apply()方法(转)

    转自:http://uule.iteye.com/blog/1158829 JS中的call()和apply()方法 博客分类: JS   1.方法定义 call方法: 语法:call([thisOb ...

  8. 理解JS中的call、apply、bind方法(*****************************************************************)

    在JavaScript中,call.apply和bind是Function对象自带的三个方法,这三个方法的主要作用是改变函数中的this指向. call.apply.bind方法的共同点和区别:app ...

  9. JS中的call()和apply()方法理解和使用

    1.方法定义call方法: 语法:obj.method.call(thisObj[,arg1[, arg2[, [,.argN]]]]) 定义:调用对象(obj)的一个方法(method),以另一个对 ...

随机推荐

  1. solarium atomic update

    https://github.com/solariumphp/solarium/issues/159

  2. c++左值和右值

    c++编程中如果出现把一个函数的返回值.强行转化后的对象 作为函数的参数传进去时,编译器会报错的情况.这时候就该注意了,你需要把该函数的参数类型前加上const修饰. 原因在于c++的左值和右值有所区 ...

  3. 基于EasyUI的Web应用程序及过去一年的总结

    前言 在这家公司服务了一年时间,一个多月之前已经提交了离职申请,好在领导都已经批准了,过几天就办理手续了,在此感谢领导的栽培与挽留,感谢各位同事在工作中的给我的帮助,感谢师傅(在我心中当他是我师傅,跟 ...

  4. 该用 QGraphicsView ? QtQuick-QML ?

    目前QtQuick (2014/3/6) 已经发展了有一段时间了,很多人在用因此我也想看看是否适合我目前的项目. 我要做的是一个类似3DMax中的材质编辑器的东西,里面有成千上万的”表单“(不知道怎么 ...

  5. Jenkins console输出乱码???

    jenkins console输出乱码??? 在jenkins中job执行shell,console中出现乱码如下: [WARNING] /home/mtime/data/jenkins/worksp ...

  6. MySQL索引原理及慢查询优化 转载

    原文地址: http://tech.meituan.com/mysql-index.html MySQL凭借着出色的性能.低廉的成本.丰富的资源,已经成为绝大多数互联网公司的首选关系型数据库.虽然性能 ...

  7. 用SignalR实现的共享画板例子

    使用HTML5的canvas画布功能,在页面进行绘画,然后通过SignalR将画布的每个点的颜色提交到服务端,服务端同时将这些画布的信息推送到其他客户端,实现共享同一个画板的功能 类似下图,在某一个浏 ...

  8. 有关uploadifive的使用经验

    这段时间做了一个项目用到uploadifive上传控件,和uploadify不同,这个控件是基于HTML5的版本而不用支持falsh,因而移动端也可以使用. 整理用过的相关属性与方法: 属性 作用 a ...

  9. winform 记住密码功能

      //登录        private void btn_Login_Click(object sender, EventArgs e)        {            //记住密码    ...

  10. .net mvc利用NPOI导入导出excel

    1.导出Excel :首先引用NPOI包(Action一定要用FileResult) /// <summary> /// 批量导出需要导出的列表 /// </summary> ...