《JavaScript应用程序设计》一一2.5 方法上下文-阿里云开发者社区

开发者社区> 华章计算机> 正文

《JavaScript应用程序设计》一一2.5 方法上下文

简介:
+关注继续查看

本节书摘来华章计算机出版社《JavaScript应用程序设计》一书中的第2章,第2.5节,作者:Eric Elliott 更多章节内容可以访问云栖社区“华章计算机”公众号查看。

2.5 方法上下文

在JavaScript中,执行函数的方式是在其引用的结尾处追加花括号,下面我们对highPass()函数做略微修改。

function highPass(number, cutoff) {
    cutoff = cutoff || this.cutoff;
    return (number >= cutoff);
}

var filter1 = {
    highPass: highPass,
    cutoff: 5
  },
  filter2 = {
    // No highPass here!
    cutoff: 3
  };

highPass()的入参包含一个必选参数Number与一个可选参数cutoff。如果未传入cutoff,函数会认为自己是作为方法在对象上(filter)调用,会使用对象(filter)中的属性cutoff而非入参cutoff。
普通函数的调用:

test('Invoking a function.', function () {
  var result = highPass(6, 5);

  equal(result, true,
    '6 > 5 should be true.');
});

警告: 一般来说,函数中的this始终是指向全局对象,除非你将函数作为对象的方法执行(使用点语法或者方括号)。所以在做函数调用时,最好先确认其this指向是否正确,以防像属性赋值这样的操作污染全局对象。
方法调用将函数与对象关联起来,像object.methodName()(点语法)、object['method Name']()(方括号语法)都属于方法调用。

test('Invoking a method.', function () {
  var result1 = filter1.highPass(3),
    result2 = highPass.call(filter2, 3),
    result3 = filter1.highPass(6);

  equal(result1, false,
    '3 >= filter1.cutoff should be false.');

  equal(result2, true,
    '3 >= filter2.cutoff should be true.');

  equal(result3, true,
    '6 >= filter1.cutoff should be true.');
});

当你通过点语法调用方法时,在方法中使用this,可以访问到对象的属性。在上例中,将入参与filter对象上的cutoff属性作比较,随后返回false,因为3明显是小于this.cutoff值。请牢记,this值的指向取决于方法在哪一个对象上执行。
在第二个例子中,call()方法(继承自Function.prototype)将highPass()方法代理到了filter2对象上,由于filter2对象中cutoff值是3而不是5,测试依然通过。
确切来说,call()方法存在于每一个函数中,理论上可以使用call()方法让函数在任意对象上进行方法调用,换句话说,它将函数中的this指向了你所指定的对象。方法签名如下:

someMethod.call(context, argument1, argument2, ...);

其中context是你希望this所指向的对象,如果想传入一组数组作为入参,可以使用apply():

someMethod.apply(context, someArray);
Function.prototype.bind()

诚然,call()与apply()方法非常实用,不过使用它们时,你需要格外小心,因为它们所绑定的this上下文指向是临时的,每次调用都需要准确无误地传入,而且时刻得确保this能够在当前函数作用域中访问到。不过每次调用都这么做略显麻烦,特别是在事件监听器中。
bind()方法可以解决这个问题,它用来将函数的this指向与目标对象绑定。bind()方法是JavaScript语言规范中的一门新特性,最开始在Prototype等JavaScript类库中出现,随后在ECMAScript5规范中被标准化,但是老版本的浏览器对它的兼容度不高,你可以考虑自己实现或者采用第三方类库。
bind()方法的使用场景之一,将事件监听器与对象绑定:

var lightbulb = {
    toggle: function toggle() {
      this.isOn = !this.isOn;
      return this.isOn;
    },
    isOn: false
  },
  toggle = lightbulb.toggle,
  lightswitch = document.getElementById('lightswitch');

lightswitch = document.getElementById('lightswitch');
lightswitch.addEventListener('click',
  lightbulb.toggle, false);

上述代码示例很好理解,事件监听器通过addEventListener方法绑定至lightswitch的DOM元素上。那么问题来了,事件监听器中的this指向并不是lightbulb对象,而是点击触发时的DOM元素,所以lightbulb的开关逻辑不会被执行。
打开界面上的开关按钮,lightbulb.isOn的值仍为false。下面来用bind()方法修复这个问题,仅需对toggle的赋值方式做略微修改。
toggle = lightbulb.toggle.bind(lightbulb);
OK,现在lightbulb的开关可以响应来自用户的操作了。

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
Java 文件上传下载管理器(控制台)
Java 文件上传下载管理器(控制台)
2737 0
《Akka应用模式:分布式应用程序设计实践指南》读书笔记2
Akka简介   Akka是什么:“Akka是在JVM上构建高并发、分布式、弹性消息驱动应用的开源工具包”。弹性意味着要积极响应失败情况,从失败中恢复的能力。   其实Akka的定义很符合响应式领域模型,这个模型有几个基本特征:   1、弹性。
1851 0
《Akka应用模式:分布式应用程序设计实践指南》读书笔记1
  作者属于Scala、Akka技术爱好者,但苦于Akka没有关于设计模式的文章,偶尔搜到《Akka应用模式》一书,如获至宝。现整理一些读书笔记和自己的感悟,以供参考。 Actor模型 Actor模型感觉还是很给力的,要是按我以前学习actor模型,绝对会对他嗤之以鼻,这玩儿意能干啥。
1541 0
JavaScript轻应用网络模块介绍
JavaScript轻应用提供了网络管理相关的功能,APP可以通过JSAPI获取网络相关的信息,并且可以接收网络连接、断开的事件。
48 0
《HTML5和JavaScript Web应用开发》——2.6 QA和设备测试
因为当前移动市场主要属于Android和iOS,进行基于WebKit的测试相当简单,我们可以像平常在桌面浏览器那样进行测试,然后在某个版本的WebKit支持的目标移动设备上运行。但是,在桌面版本的Chrome或者Safari上测试应用,并不意味着在所有基于WebKit的移动浏览器上都能正常工作,也不意味着WebKit能够完全代表移动Web。
1101 0
《JavaScript高级程序设计(第3版)》阅读笔记
第6章 面向对象的程序设计 6.2 创建对象 6.2.1 工厂模式 JavaScript创建对象(一)—— 工厂模式 6.
833 0
JavaScript轻应用UI介绍
本文档在此基础上介绍下轻应用UI是如何开发的。与前者相比,从应用代码的文件结构看,需要增加页面文件,并在全局配置中增加页面路径相关的信息即可。
84 0
10059
文章
0
问答
来源圈子
更多
+ 订阅
文章排行榜
最热
最新
相关电子书
更多
《2021云上架构与运维峰会演讲合集》
立即下载
《零基础CSS入门教程》
立即下载
《零基础HTML入门教程》
立即下载