《Web 前端面试指南》2、JavaScript 的 Bind 函数进阶
使用 Bind() 设置方法中 this 对象
//<button>获取随机的人</button>
//<input type="text">
var user = {
data:[
{name:"张三", age:37},
{name:"李四", age:43}
],
clickHandler:function (event) {
var randomNum = ((Math.random () * 2 | 0) + 1) - 1; // 随机获取 0 或者 1
// 从数组中取出值,赋值到 Input 文本框内
$ ("input").val (this.data[randomNum].name + " " + this.data[randomNum].age);
}
}
// 绑定事件
$ ("button").click (user.clickHandler);
当点击的时候,会报错,因为 clickHandler 方法中的 this 指向的是 button 元素。
为了解决这个问题,我们可以使用 bind 方法。
使用如下代码:
$ ("button").click (user.clickHandler.bind (user));
代替之前:
$ ("button").click (user.clickHandler);
但是,在 IE9 以下和 Firefox 3.x 的浏览器中,是不支持 Bind 方法的,所以可以考虑加入如下方法。
// 判断是否支持 Bind 方法
if (!Function.prototype.bind) {
Function.prototype.bind = function (oThis) {
if (typeof this !== "function") {
throw new TypeError (" Function.prototype.bind - 绑定错误");
}
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;
};
}
我们继续我们的例子,考虑如下代码:
// 全局变量
var data = [
{name:"王五", age:12},
{name:"陈六", age:14}
]
var user = {
// 局部变量
data:[
{name:"张三", age:37},
{name:"李四", age:43}
],
showData:function (event) {
var randomNum = ((Math.random () * 2 | 0) + 1) - 1;
console.log (this.data[randomNum].name + " " + this.data[randomNum].age);
}
}
var showDataVar = user.showData;
showDataVar (); // 王五 12 (这里说明是从 全局变量而不是局部变量中取数据)
当执行 showDataVar() 时,this 指向的是全局变量,而不是局部变量。这是因为 showDataVar() 是作为全局函数执行的,它是绑定的是全局作用域,也就是浏览器的 window 对象。
同样,我们可以通过使用 bind 方法指定 this 的值来解决这个问题:
// 把 showData 绑定到 user 对象
var showDataVar = user.showData.bind (user);
// 现在我们得到了 user 的值
showDataVar (); // 张三 43
Bind() 可以实现借调方法 (Borrow Methods)
我们知道在 JavaScript 中我们可以传递函数,返回函数和借调函数。Bind() 方法会使借调函数变地非常简单易用。
如下代码:
// 这里有个 cars 对象,它里面没有任何函数。
var cars = {
data:[
{name:"黎明", age:14},
{name:"刘德华", age:2}
]
}
// 我们可以从上面例子中借调 user 对象中 showData () 函数。
// 我们绑定 user.showData 函数处理 cars 对象。
cars.showData = user.showData.bind (cars);
cars.showData (); // 黎明 14
这样写的代码有个问题,就是会在 cars 对象中,新加一个函数(showData),这可能不是我们的本意,因为可能 cars 对象中此前已经有了一个叫 showData 的属性或者函数了。我们不想意外覆盖它。在下文中会说明,最好的借调方式是使用 Apply 或者 Call。
JavaScript 中的 Bind() 可以实现函数柯里化(Function Currying)
柯里化:是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数且返回结果的新函数的技术。百度百科的定义
首先,看以下代码,是个有三个参数的方法 greet():
function greet (gender, age, name) {
// 如果性别为男,使用 "先生", 否则使用 "女士"。
var salutation = gender === "male" ? "先生" : "女士";
if (age > 25) {
return "你好," + name + salutation + "。";
}
else {
return "你好," + name + "。";
}
}
接下来,我们使用 bind() 来进行函数柯里化()。
// 因为我们不想使用 this 关键字,所以第一个参数我们传递 null。
var greetAnAdultMale = greet.bind (null, "male", 45);
greetAnAdultMale ("李连杰"); // "你好,李连杰先生。"
var greetAYoungster = greet.bind (null, "", 16);
greetAYoungster ("成龙"); // "你好, 成龙。"
greetAYoungster ("李小龙"); // "你好,李小龙。"
当我们使用 bind() 进行柯里化的时候,除了最后一个外,所有的参数都被预设置好了。
《Web 前端面试指南》2、JavaScript 的 Bind 函数进阶的更多相关文章
- web前端面试试题总结---javascript篇
JavaScript 介绍js的基本数据类型. Undefined.Null.Boolean.Number.String. ECMAScript 2015 新增:Symbol(创建后独一无二且不可变的 ...
- 《Web 前端面试指南》1、JavaScript 闭包深入浅出
闭包是什么? 闭包是内部函数可以访问外部函数的变量.它可以访问三个作用域:首先可以访问自己的作用域(也就是定义在大括号内的变量),它也能访问外部函数的变量,和它能访问全局变量. 内部函数不仅可以访问外 ...
- web前端面试试题总结---html篇
HTML Doctype作用?标准模式与兼容模式各有什么区别? (1).<!DOCTYPE>声明位于位于HTML文档中的第一行,处于 <html> 标签之前.告知浏览器的解析器 ...
- web前端面试总结
本文由我收集总结了一些前端面试题,初学者阅后也要用心钻研其中的原理,重要知识需要系统学习.透彻学习,形成自己的知识链.万不可投机取巧,临时抱佛脚只求面试侥幸混过关是错误的!也是不可能的! 前端还是一个 ...
- web前端面试试题总结---其他
其他问题 原来公司工作流程是怎么样的,如何与其他人协作的?如何夸部门合作的? 你遇到过比较难的技术问题是?你是如何解决的? 设计模式 知道什么是singleton, factory, strategy ...
- web前端面试试题总结---css篇
CSS 介绍一下标准的CSS的盒子模型?低版本IE的盒子模型有什么不同的? (1)有两种, IE 盒子模型.W3C 盒子模型: (2)盒模型: 内容(content).填充(padding).边界(m ...
- Web前端面试笔试题总结
最近一段时间要毕业了,忙着找工作,见过不少笔试面试题,自己总结了一些加上网上找的一些整合了一下.答案暂时都东拼西凑出来了,但是还是先不发出来,一方面是答案并不是唯一的并且自己的答案不能保证对,另一方面 ...
- 2016年Web前端面试题目汇总
转载: 2016年Web前端面试题目汇总 以下是收集一些面试中经常会遇到的经典面试题以及自己面试过程中未解决的问题,通过对知识的整理以及经验的总结,重新巩固自身的前端基础知识,如有错误或更好的答案,欢 ...
- 百度web前端面试2015.10.18
邮件里通知的周日下午两点参加百度校招面试,我13:10分就到了,前台先让我拿了个面试资格单(上面是我的信息),然后在web前端面试入口排队,面试在百度食堂举行的,等了大概1个小时,放我去面试.都是一对 ...
随机推荐
- gulp安装
1. npm install gulp -g 全局安装 npm install gulp --save-dev 安装文件内,纪录于package.json 接著安装插件,完成下列任务 ...
- 1.dubbo的安装 quickstart
按照官网给定的指导,执行下面的步骤即可 1.Import the dubbo source code to eclipse project 在eclipse中安装git插件 egit 直接可以从git ...
- js+dom开发第十六天
一.css常用标签及页面布局 1.常用标签 position(定位) z-index(定位多层顺序) background(背景) text-align(针对字符自动左右居中) margin(外边距) ...
- Django socketio 安装
如果你还没有安装过 gevent,首先需要安装 libevent, 编译安装 libevent 需要安装 Pyhton 开发库. 在Debain上可以运行如下指令: $ sudo apt-get in ...
- 如何自定义RecycleView item的间距
引言 在以前使用ListView和GridView时,设置item之间的间距还是相对比较简单的,因为它们的基本属性里面Android已经定义好了,可以直接设置属性值即可.但Google为了通用性和灵活 ...
- UBOOT的多支持性与可裁剪性
UBOOT功能强大,适用于多种操作系统,多种处理器架构. 在阅读它的源码时,可以看到cpu目录有各种处理器,而board目录有各种开发板.但是,对于一个特定的实验平台,例如TQ2440开发板,它用到的 ...
- SharePoint 获取Lookup 字段的值
获取某个List里的Lookup字段的值是很普遍的事,那么我们将它封装起来 获取Lookup字段值的方法: /// <summary> /// To get lookup field Id ...
- 深入浅出C语言中的堆和栈
在谈堆栈的时候,我在这有必要把计算机的内存结构给大家简单的介绍下(高手们可以直接飘过) 一. 内存结构 每个程序一启动都有一个大小为4GB的内存,这个内存叫虚拟内存,是概念上的,真正能用到的,只是 ...
- IIS短文件名漏洞修补方法之一改注册表一个注意项
1)1.png 为漏洞存在没有做任何修复的时候的扫描 修复:2) 修改注册表键值: HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\FileSy ...
- python 单元测试
http://blog.csdn.net/five3/article/details/7104466