《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 ...
随机推荐
- LIS问题分析
题目来源,待字闺中,原创@陈利人 ,欢迎大家继续关注微信公众账号"待字闺中" 原题这个LIS问题,可不是Longest Increasing Subsequence,而是Large ...
- 主从mysql 同步设置
GRANT REPLICATION SLAVE ON *.* TO 'root'@'%' IDENTIFIED BY 'zhoubt';grant all privileges on *.* to ...
- svn跨机备份
#!/bin/sh svn_bak_dir='/svndata/cloudil' svn_server='svn://172.16.40.200:9999' user=adminread pass=a ...
- setStyleSheet来设定窗口部件的样式
使用setStyleSheet来设置图形界面的外观:QT Style Sheets是一个很有利的工具,允许定制窗口的外观,此外还可以用子类QStyle来完成,他的语法很大比重来源于html的CSS,但 ...
- poj1639 Picnic Planning 最小度数限制生成树
题意:若干个人开车要去park聚会,可是park能停的车是有限的,为k.所以这些人要通过先开车到其它人家中,停车,然后拼车去聚会.另外,车的容量是无限的,他们家停车位也是无限的. 求开车总行程最短. ...
- RBAC用户角色权限设计方案
RBAC(Role-Based Access Control,基于角色的访问控制),就是用户通过角色与权限进行关联.简单地说,一个用户拥有若干角色,每一个角色拥有若干权限.这样,就构造成“用 户-角色 ...
- [Android学习笔记]some tips
集合合并去重: listA.removeAll(listB); listA.addAll(listB); android:singleLine="true"//单行显示 andro ...
- Linux几种关机(重启)相关命令
在linux下一些常用的关机/重启命令有shutdown.halt.reboot.及init,它们都可以达到重启系统的目的,但每个命令的内部工作过程是不同的,通过本文的介绍,希望你可以更加灵活的运用各 ...
- Java中double变量精确到小数点后几(2)位
import java.math.BigDecimal; import java.text.NumberFormat; public class Java中double类型的数据精确到小数点后两位 { ...
- POJ2584 T-Shirt Gumbo【二分图多重匹配】
题目链接: id=2584">http://poj.org/problem?id=2584 题目大意: 如今有5种型号(S.M.L.X.T)的衣服要发放给N个參赛队员.给出每一个參赛者 ...