javascript中的Function.prototye.bind

   这篇文章主要介绍了javascript中的Function.prototye.bind的相关资料,需要的朋友可以参考下

  函数绑定(Function binding)很有可能是你在开始使用JavaScript时最少关注的一点,但是当你意识到你需要一个解决方案来解决如何在另一个函数中保持this上下文的时候,你真正需要的其实就是 Function.prototype.bind(),只是你有可能仍然没有意识到这点。

  第一次遇到这个问题的时候,你可能倾向于将this设置到一个变量上,这样你可以在改变了上下文之后继续引用到它。很多人选择使用 self, _this 或者 context 作为变量名称(也有人使用 that)。这些方式都是有用的,当然也没有什么问题。但是其实有更好、更专用的方式。

  我们真正需要解决的问题是什么?

  在下面的例子代码中,我们可以名正言顺地将上下文缓存到一个变量中:

  ?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

var myObj = {
 
specialFunction: function () {
 
},
 
anotherSpecialFunction: function () {
 
},
 
getAsyncData: function (cb) {
cb();
},
 
render: function () {
var that = this;
this.getAsyncData(function () {
that.specialFunction();
that.anotherSpecialFunction();
});
}
};
 
myObj.render();

  如果我们简单地使用 this.specialFunction() 来调用方法的话,会收到下面的错误:

  Uncaught TypeError: Object [object global] has no method 'specialFunction'

  我们需要为回调函数的执行保持对 myObj 对象上下文的引用。 调用 that.specialFunction()让我们能够维持作用域上下文并且正确执行我们的函数。 然而使用 Function.prototype.bind() 可以有更加简洁干净的方式:

  ?

1
2
3
4
5
6
7
8
9
10
11

render: function () {
 
this.getAsyncData(function () {
 
this.specialFunction();
 
this.anotherSpecialFunction();
 
}.bind(this));
 
}

  我们刚才做了什么?

  .bind()创建了一个函数,当这个函数在被调用的时候,它的 this 关键词会被设置成被传入的值(这里指调用bind()时传入的参数)。因此,我们传入想要的上下文,this(其实就是 myObj),到.bind()函数中。然后,当回调函数被执行的时候, this 便指向 myObj 对象。

  如果有兴趣想知道 Function.prototype.bind() 内部长什么样以及是如何工作的,这里有个非常简单的例子:

  ?

1
2
3
4
5
6

Function.prototype.bind = function (scope) {
var fn = this;
return function () {
return fn.apply(scope);
};
}

  还有一个非常简单的用例:

  ?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

var foo = {
x: 3
}
 
var bar = function(){
console.log(this.x);
}
 
bar();
// undefined
 
var boundFunc = bar.bind(foo);
 
boundFunc();
// 3

  我们创建了一个新的函数,当它被执行的时候,它的 this 会被设置成 foo —— 而不是像我们调用 bar() 时的全局作用域。

  浏览器支持

  Browser Version support

  Chrome 7

  Firefox (Gecko) 4.0 (2)

  Internet Explorer 9

  Opera 11.60

  Safari 5.1.4

  正如你看到的,很不幸,Function.prototype.bind 在IE8及以下的版本中不被支持,所以如果你没有一个备用方案的话,可能在运行时会出现问题。

  幸运的是,Mozilla Developer Network(很棒的资源库),为没有自身实现 .bind() 方法的浏览器提供了一个绝对可靠的替代方案:

  ?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

if (!Function.prototype.bind) {
Function.prototype.bind = function (oThis) {
if (typeof this !== "function") {
 
// closest thing possible to the ECMAScript 5 internal IsCallable function
throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable");
}
 
var aArgs = Array.prototype.slice.call(arguments, 1),
fToBind = this,
fNOP = function () {},
fBound = function () {
return fToBind.apply(this instanceof fNOP && oThis
? this
: oThis,
aArgs.concat(Array.prototype.slice.call(arguments)));
};
 
fNOP.prototype = this.prototype;
fBound.prototype = new fNOP();
 
return fBound;
};
}

  适用的模式

  在学习技术点的时候,我发现有用的不仅仅在于彻底学习和理解概念,更在于看看在手头的工作中有没有适用它的地方,或者比较接近它的的东西。我希望,下面的某些例子能够适用于你的代码或者解决你正在面对的问题。

  CLICK HANDLERS(点击处理函数)

  一个用途是记录点击事件(或者在点击之后执行一个操作),这可能需要我们在一个对象中存入一些信息,比如:

  ?

1
2
3
4
5
6
7

var logger = {
x: 0,
updateCount: function(){
this.x++;
console.log(this.x);
}
}

  我们可能会以下面的方式来指定点击处理函数,随后调用 logger 对象中的 updateCount() 方法。

  ?

1
2
3

document.querySelector('button').addEventListener('click', function(){
logger.updateCount();
});

  但是我们必须要创建一个多余的匿名函数,来确保 updateCount()函数中的 this 关键字有正确的值。

  我们可以使用如下更干净的方式:

  document.querySelector('button').addEventListener('click', logger.updateCount.bind(logger));

  我们巧妙地使用了方便的 .bind() 函数来创建一个新的函数,而将它的作用域绑定为 logger 对象。

  SETTIMEOUT

  如果你使用过模板引擎(比如Handlebars)或者尤其使用过某些MV*框架(从我的经验我只能谈论Backbone.js),那么你也许知道下面讨论的关于在渲染模板之后立即访问新的DOM节点时会遇到的问题。

  假设我们想要实例化一个jQuery插件:

  ?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

var myView = {
 
template: '/* 一个包含 <select /> 的模板字符串*/',
 
$el: $('#content'),
 
afterRender: function () {
this.$el.find('select').myPlugin();
},
 
render: function () {
this.$el.html(this.template());
this.afterRender();
}
}
 
myView.render();

  你或许发现它能正常工作——但并不是每次都行,因为里面存在着问题。这是一个竞争的问题:只有先到达的才能获胜。有时候是渲染先到,而有时候是插件的实例化先到。【译者注:如果渲染过程还没有完成(DOM Node还没有被添加到DOM树上),那么find(‘select')将无法找到相应的节点来执行实例化。】

  现在,或许并不被很多人知晓,我们可以使用基于 setTimeout() 的 slight hack来解决问题。

  我们稍微改写一下我们的代码,就在DOM节点加载后再安全的实例化我们的jQuery插件:

  ?

1
2
3
4
5
6
7
8

afterRender: function () {
this.$el.find('select').myPlugin();
},
 
render: function () {
this.$el.html(this.template());
setTimeout(this.afterRender, 0);
}

  然而,我们获得的是 函数 .afterRender() 不能找到 的错误信息。

  我们接下来要做的,就是将.bind()使用到我们的代码中:

  ?

1
2
3
4
5
6
7
8
9
10
11
12

//
 
afterRender: function () {
this.$el.find('select').myPlugin();
},
 
render: function () {
this.$el.html(this.template());
setTimeout(this.afterRender.bind(this), 0);
}
 
//

  以上所述就是本文的全部内容了,希望大家能够喜欢。

时间: 2024-09-15 19:19:00

javascript中的Function.prototye.bind的相关文章

javascript中的Function.prototye.bind_javascript技巧

函数绑定(Function binding)很有可能是你在开始使用JavaScript时最少关注的一点,但是当你意识到你需要一个解决方案来解决如何在另一个函数中保持this上下文的时候,你真正需要的其实就是 Function.prototype.bind(),只是你有可能仍然没有意识到这点. 第一次遇到这个问题的时候,你可能倾向于将this设置到一个变量上,这样你可以在改变了上下文之后继续引用到它.很多人选择使用 self, _this 或者 context 作为变量名称(也有人使用 that)

javascript 前端-javascript中文本输入框通过bind方法绑定得到焦点和失去焦点时间

问题描述 javascript中文本输入框通过bind方法绑定得到焦点和失去焦点时间 通过id找到文本输入框,将该文本输入框在JavaScript中通过bind方法绑定得到焦点和失去焦点事件,不要在html中实现! 解决方案 $("input[@type=text]").bind({"focus":function(){alert(new Date())},"blur":function(){alert(new Date()}}) 解决方案二:

深入浅析JavaScript中的Function类型_javascript技巧

Function是javascript里最常用的一个概念,javascript里的function是最容易入手的一个功能,但它也是javascript最难理解最难掌握的一个概念. 1. Function类型是js中引用类型之一,每个函数实际上都是Function类型的实例对象,具有自己的属性和方法.正因为函数式对象,所以函数名实际上也是一个指向函数对象的指针. 2. 常用的函数定义方式 1. 函数声明: function sum(a , b ){ return a+b; } 2. 表达式: va

浅谈javascript中的Function和Arguments_javascript技巧

javascript的Function 属性: 1.Arguments对象 2.caller  对调用单前函数的Function的引用,如果是顶层代码调用,  则返回null(firefox返回undefined).  注:只有在代码执行时才有意义 3.length  声明函数是指定的命名参数的个数(函数定义是,定义参数的个数) 4.prototype  一个对象,用于构造函数,这个对象定义的属性和方法  由构造函数创建的所有对象共享. 方法:  applay() --> applay(this

JavaScript中的function使用方法

JavaScript入门易,可深究起来,竟搞得我如此混乱,这恐怕就是弱类型语言的特点吧?写惯了C++,还真是不适应.近日在google上搜来搜去,学习了半天function.this和prototype,这就总结一下,但愿能把它们理清楚.这是第一篇,关于JavaScript中的function. 参考了一些文章,我认为JavaScript中的function可以有以下两种用法:一是做"普通逻辑代码容器",也就是我们通常意义上的函数.方法,和我们C/C++里的函数没什么大分别,只是写法稍

深入理解JS中的Function.prototype.bind()方法_基础知识

前言 对于函数绑定(Function binding)很有可能是大家在使用JavaScript时最少关注的一点,但是当你意识到你需要一个解决方案来解决如何在另一个函数中保持this上下文的时候,你真正需要的其实就是 Function.prototype.bind() ,只是你有可能仍然没有意识到这点. 第一次遇到这个问题的时候,你可能倾向于将this设置到一个变量上,这样你可以在改变了上下文之后继续引用到它. 一. bind的语法 bind() 方法的主要作用就是将函数绑定至某个对象,bind(

javascript中call apply 与 bind方法详解_基础知识

在JavaScript中,call.apply和bind是Function对象自带的三个方法,本文将通过几个场景的应用,来详细理解三个方法. call() call() 方法在使用一个指定的this值和若干个指定的参数值的前提下调用某个函数或方法. 当调用一个函数时,可以赋值一个不同的 this 对象.this 引用当前对象,即 call 方法的第一个参数. 通过 call 方法,你可以在一个对象上借用另一个对象上的方法,比如Object.prototype.toString.call([]),

浅谈Javascript中的Function与Object_javascript技巧

Function 函数就是对象,代表函数的对象就是函数对象.所有的函数对象是被Function这个函数对象构造出来的.也就是说,Function是最顶层的构造器.它构造了系统中所有的对象,包括用户自定义对象,系统内置对象,甚至包括它自已. Object Object是最顶层的对象,所有的对象都将继承Object的原型,你也要知道Object也是一个函数对象,所以说Object是被Function构造出来的. Function 与Object 关系图: 复制代码 代码如下: <script typ

JavaScript中的Function函数_javascript技巧

首先给大家介绍JavaScript中function定义函数的几种方法: 1.最基本的作为一个本本分分的函数声明使用. 复制代码 代码如下: function func(){} 或 复制代码 代码如下: var func=function(){}; 2.作为一个类构造器使用: function class(){} class.prototype={}; var item=new class(); 3.作为闭包使用: (function(){ //独立作用域 })(); 4.可以作为选择器使用: