《Javascript高级程序设计》读书笔记之bind函数详解
为什么需要bind
var name = "The Window";
var object = {
name: "My Object",
getNameFunc: function () {
return function () {
return this.name;
}
}
}; alert(object.getNameFunc()()); //"The Window"
object.getNameFunc()返回一个匿名函数,在全局环境调用该函数,this指向的全局对象
解决这一问题,可以像下面这样,将匿名函数外部作用域中this对象保存在闭包能够访问到的变量中
var name = "The Window";
var object = {
name: "My Object",
getNameFunc: function () {
var that = this;
return function () {
return that.name;
}
}
}; alert(object.getNameFunc()()); //"My Object"
上述解决方法需要修改对象的方法,如果不能修改原对象的方法,该如何做呢?
这时,我们可以像下面这样,使用apply或call方法指定函数的作用域
var name = "The Window";
var object = {
name: "My Object",
getNameFunc: function () {
return function () {
return this.name;
}
}
};
var func=object.getNameFunc();
alert(func.apply(object)); //"My Object"
通过apply、call,已经可以输出预期的My Object
但是,每次调用时都需要以func.apply(object)的形式调用,这不是很怪么
理想的调用方式,当然是在通过某种处理后,之后可以以func()形式调用,像下面这样
var name = "The Window";
var object = {
name: "My Object",
getNameFunc: function () {
return function () {
return this.name;
}
}
};
var func=object.getNameFunc();
func=func.bind(object);
alert(func()); //"My Object"
ECMAScript 5中的bind
ECMAScript 5定了了bind方法,这个方法会创建一个函数实例,其this值会被绑定到传给bind函数的值,上面代码给出了bind函数的使用方式,再给一个简单示例。
window.color="red";
var o={color:"blue"};
function sayColor(){
alert(this.color);
} var func=sayColor.bind(o);
func();//"blue"
虽然大部分浏览器中已经可以使用ECMAScript 5定义的这个方法,但在少数不支持的浏览器中你还是会遇到兼容性问题,这是如何处理呢?
通过上面apply、call方法使用示例 ,可以像下面这样提供一个解决方案
Function.prototype.bind=Function.prototype.bind||
function(context){
var self=this;
return function()
{
return self.apply(context,arguments);
}
}
Prototype.js中的bind
// The .bind method from Prototype.js
Function.prototype.bind = function(){
var fn = this, args = Array.prototype.slice.call(arguments), object = args.shift();
return function(){
return fn.apply(object,
args.concat(Array.prototype.slice.call(arguments)));
};
};
上述代码中,
args=Array.prototype.slice.call(arguments)将调用bind函数时参数集合arguments转换为数组array
object=args.shift()将args数组第一个元素取出作为当前对象
匿名函数中,调用args.concat(Array.prototype.slice.call(arguments))是为了将调用匿名函数时传入的参数与调用bind时参数合并成一个参数数组
以一个调用示例来看上述过程
var obj = { x: 'prop x' };
//args = Array.prototype.slice.call(arguments)后args = [obj, 12, 23 ]
//object=args.shift()后,args =[12, 23] ,object =obj var boundExample = example.bind(obj, , );
boundExample(, ); // arguments => 36, 49 ,调用args.concat(Array.prototype.slice.call(arguments))后,arguments that our example() function receives => [12, 23, 36, 49]
Firefox中的bind
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, ),
fToBind = this,
fNOP = function () {},
fBound = function () {
return fToBind.apply(this instanceof fNOP && oThis
? this
: oThis || window,
aArgs.concat(Array.prototype.slice.call(arguments)));
}; fNOP.prototype = this.prototype;
fBound.prototype = new fNOP(); return fBound;
};
}
Firefox为bind提供了一个兼容实现,主要代码与prototype.js中实现类似,不再逐句解释了
《Javascript高级程序设计》读书笔记之bind函数详解的更多相关文章
- javascript高级程序设计读书笔记
第2章 在html中使用javascript 一般都会把js引用文件放在</body>前面,而不是放在<head>里, 目的是最后读取js文件以提高网页载入速度. 引用js文 ...
- JavaScript高级程序设计-读书笔记(7)
第22章 高级技巧 1.高级函数 (1)安全的类型检测 在任何值上调用Object原生的toString()方法,都会返回一个[object NativeConstructorName]格式的字符串. ...
- javascript高级程序设计读书笔记-事件(一)
读书笔记,写的很乱 事件处理程序 事件处理程序分为三种: 1.html事件2. DOM0级,3,DOM2级别 没有DOM1 同样的事件 DOM0会顶掉html事件 因为他们都是属性 而 ...
- javascript高级程序设计读书笔记----引用类型
Array类型. ECMAScript数组的每一项可以保存任何类型的数据. 数组大小是可以动态调整的. 创建数组第一种基本方式方式: 使用Array构造函数 var colors = new ...
- JavaScript高级程序设计读书笔记之JSON
JSON(JavaScript Object Notation)JavaScript对象表示法.JSON是JavaScript的一个严格的子集,利用了JavaScript中的一些模式来表示结构化数据. ...
- javascript高级程序设计读书笔记----函数表达式
定义函数两种方式: 1.函数声明 function sayHi(){ alert("Hi"); } sayHi();//调用函数 2.函数表达式 var sayHi = funct ...
- Javascript高级程序设计读书笔记(第六章)
第6章 面向对象的程序设计 6.2 创建对象 创建某个类的实例,必须使用new操作符调用构造函数会经历以下四个步骤: 创建一个新对象: 将构造函数的作用域赋给新对象: 执行构造函数中的代码: 返回新 ...
- JavaScript高级程序设计 读书笔记
第一章 JavaScript 简介 第二章 Html中使用JavaScript 第三章 基本概念 第四章 变量,作用域,内存 第五章 引用类型 第六章 面向对象 第七章 函数表达式 第八章 BOM 第 ...
- JavaScript高级程序设计-读书笔记(6)
第20章 JSON JSON是一个轻量级的数据格式,可以简化表示复杂数据结构的工作量 JSON的语法可以表示一下三种类型的值 l 简单值:使用与JavaScript相同的语法,可以在JS ...
随机推荐
- Python标准库:内置函数dict(iterable, **kwarg)
本函数是从可迭代对象来创建新字典.比方一个元组组成的列表,或者一个字典对象. 样例: #dict() #以键对方式构造字典 d1 = dict(one = 1, two = 2, a = 3) pri ...
- HDU 5045(Contest-费用流)[template:费用流]
Contest Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others) Total Submi ...
- 让notepad.exe的utf8不添加BOM
实在是厌烦了notepad的utf8模式了,于是决定修改之,方案如下: 使用任何支持hex模式的编辑器打开%SystemRoot%/system32/notepad.exe查找二进制串56 8D 45 ...
- 总结showModalDialog在开发中的一些问题
一.在页面调用window.open()函数后,可以直接在打开的页面中用window.opener来调用父页面的方法,然而如果用showModalDialog打开一个模态窗口,就不能通过window. ...
- SDUT 1304-取数字问题(DFS)
取数字问题 Time Limit: 1000ms Memory limit: 65536K 有疑问?点这里^_^ 题目描写叙述 给定M×N的矩阵,当中的每一个元素都是-10到10之间的整数.你的 ...
- java学习笔记12--国际化
java学习笔记12--国际化 国际化的操作就是指一个程序可以同时适应多门语言,即:如果现在程序者是中国人,则会以中文为显示文字,如果现在程序的使用者是英国人,则会以英语为显示的文字,也就是说可以通过 ...
- MVVM Light须要注意的10个问题
MVVM Light须要注意的10个问题 从使用XAML技术基础開始(实际上并非非常久曾经).我便关注MVVM(Model – View – ViewModel)模式.偶然接触到MVVM Light不 ...
- ubuntu安装软件的方式
ubuntu安装软件的方式: 通常的我们能够在ubuntu软件中心和新立得软件包管理器找到自己想要的软件,直接选择就能够自己主动下载并安装到电脑中,不想要的时候随时能够再从那里面卸载.这是第一种方法, ...
- 简单的三方登录SDK示例,Android Activity之间数据的传递
先建立Library工程,即普通工程然后在Android的属性勾选Library选项. 这里建立的工程为 mySdk ,Activity名为LoginActivity. LoginActivity代码 ...
- 动态拼接lambda表达式树
前言 最近在优化同事写的代码(我们的框架用的是dapperLambda),其中有一个这样很普通的场景——界面上提供了一些查询条件框供用户来进行过滤数据.由于dapperLambda按条件查询时是传入表 ...