《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的开关可以响应来自用户的操作了。

相关文章
|
15天前
|
JavaScript 前端开发 API
详解队列在前端的应用,深剖JS中的事件循环Eventloop,再了解微任务和宏任务
该文章详细讲解了队列数据结构在前端开发中的应用,并深入探讨了JavaScript的事件循环机制,区分了宏任务和微任务的执行顺序及其对前端性能的影响。
|
2天前
|
前端开发 JavaScript 关系型数据库
前端的全栈之路:基于 Vue3 + Nest.js 全栈开发的后台应用
这篇文章介绍了一个名为Vue3Admin的全栈后台应用,前端基于SoybeanAdmin二次开发,后端基于Nest.js。主要使用了Vue3.5、AntDesignVue、UnoCSS、Pinia等前端技术栈,以及Nest.js、PostgreSQL、Prisma等后端技术栈。文章详细描述了系统的功能设计,包括动态国际化语言配置、登录用户操作日志、用户和角色权限映射、动态路由菜单、消息公告发布及前端业务功能等。同时,也提供了项目运行所需的环境和依赖,以及如何拉取代码、安装依赖和启动项目的方法。最后,文章展示了项目的演示图,并对项目进行了总结,指出项目未经严格测试,仅供学习交流使用。
前端的全栈之路:基于 Vue3 + Nest.js 全栈开发的后台应用
|
1天前
|
存储 JavaScript 前端开发
如何使用Vue.js实现一个简单的待办事项应用
【10月更文挑战第1天】如何使用Vue.js实现一个简单的待办事项应用
12 5
|
1天前
|
监控 前端开发 UED
Nuxt.js 应用中的 page:transition:finish 钩子详解
Nuxt.js 应用中的 page:transition:finish 钩子详解
|
1天前
|
JavaScript 前端开发 开发者
【干货拿走】JavaScript中最全的数据类型判断方法!!!!
【干货拿走】JavaScript中最全的数据类型判断方法!!!!
6 1
|
15天前
|
JavaScript 开发者
深入理解Node.js事件循环及其在后端开发中的应用
【8月更文挑战第57天】本文将带你走进Node.js的事件循环机制,通过浅显易懂的语言和实例代码,揭示其背后的工作原理。我们将一起探索如何高效利用事件循环进行异步编程,提升后端应用的性能和响应速度。无论你是Node.js新手还是有一定经验的开发者,这篇文章都能给你带来新的启发和思考。
|
15天前
|
自然语言处理 JavaScript 前端开发
JS中this的应用场景,再了解下apply、call和bind!
该文章深入探讨了JavaScript中`this`关键字的多种应用场景,并详细解释了`apply`、`call`和`bind`这三个函数方法的使用技巧和差异。
|
17天前
|
JavaScript 前端开发 API
javaScript中常用的String方法以及注意点总结
本文总结了JavaScript中常用的String对象的方法及其注意事项,包括大小写转换、字符获取、子字符串截取、字符串拼接、去除空格、替换、分割以及查找字符串中字符的索引等操作。提供了每种方法的使用示例代码,帮助理解它们的具体用法和差异。
29 2
|
18天前
|
JavaScript 前端开发
JS之concat方法
本文介绍了JavaScript中`concat`方法的使用,展示了如何利用该方法来合并数组,包括与字符串、数字、对象等类型的拼接,以及使用扩展运算符进行合并的示例。
11 0
JS之concat方法
|
20天前
|
自然语言处理 前端开发 JavaScript
探索JavaScript中的闭包及其实际应用
本文深入探讨了JavaScript中闭包的概念、特性及其在实际项目中的应用。通过具体示例,详细讲解了闭包的创建方法和用途,揭示了闭包在数据保护和模块化开发中的重要性。同时,还讨论了闭包可能带来的内存管理问题及优化策略,为前端开发者提供了全面的闭包知识和实践指导。