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

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

时间: 2024-11-10 11:33:14

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

《JavaScript应用程序设计》一一2.2 函数声明

2.2 函数声明 在JavaScript中有多种定义函数的方法,不同方法各有优缺点. function foo() { /* Warning: arguments.callee is deprecated. Use with caution. Used here strictly for illustration. */ return arguments.callee; } foo(); //=> [Function: foo] 在这段代码中,foo()是一个函数声明.正如在"变量提升&q

深入JavaScript高级程序设计之对象、数组(栈方法,队列方法,重排序方法,迭代方法)_javascript技巧

继承是OO语言中的一个最为人津津乐道的概念. 许多OO语言都支持两种继承方式:接口继承和实现继承. 接口继承只继承方法签名,而实现继承则继承实际的方法. 如其所述,由于函数没有签名,在ECMAScript中无法实现接口继承. ECMAScript只支持实现继承,而且其实现继承主要是依靠原型链来实现的. 1.使用对象字面量定义对象 var person={}; 使用这种方式创建对象时,实际上不会调用Object构造函数. 开发人员更喜欢对象字面量的语法. 2.有时候需要传递大量可选参数的情形时,一

《JavaScript应用程序设计》一一2.10 参数命名

2.10 参数命名 函数被传入的参数数量称为元数 (arity),一般来说函数的元数应该尽可能的精简,但还是避免不了出现极多个元数的调用场景.多元数的问题在于每个参数都必须按照先后顺序被传入,即使个别参数是可选的.要记住这些顺序本身就是一个令人头疼的问题,而且给函数传入无用的参数,对功能本身而言也没有意义.在下面的示例中,createUser()是一个用于创建用户账户的函数,userProto是用户账户的默认配置,可以用createUser()中传入的参数将之覆盖. var userProto

JavaScript面向对象程序设计(2) 数组

或许你会奇怪,面向对象的程序设计为什么从数组开始讲起?这是因为--其间的种种 关系吧--嘿嘿,这里先卖个关子,先来看看我们熟悉的数组在JavaScript里面是什么样 子的. 1.创建数组 在JavaScript中有很多创建数组的方法.比如使用Array函数.不过 这不是现在我们要讲述的.现在我们使用简单的方括号"[]"的办法来创建数组. var objAyyar = []; // 1 var objAyyar = [2]; // 2 var objAyyar = ["a&q

JavaScript高级程序设计(第3版)学习笔记7 js函数(上)_基础知识

变量类型 在说函数之前,先来说说变量类型. 1.变量:变量在本质上就是命名的内存空间. 2.变量的数据类型:就是指变量可以存储的值的数据类型,比如Number类型.Boolean类型.Object类型等,在ECMAScript中,变量的数据类型是动态的,可以在运行时改变变量的数据类型. 3.变量类型:是指变量本身的类型,在ECMAScript中,变量类型就只有两种:值类型和引用类型.当变量的数据类型是简单数据类型时,变量类型就是值类型,当变量的数据类型是对象类型时,变量类型就是引用类型.在不引起

JavaScript高级程序设计(第3版)学习笔记3 js简单数据类型_基础知识

ECMAScript是一种动态类型的语言,构建于5种简单数据类型(Undefined.Null.Boolean.Number.String)和一种复杂数据类型(Object)的基础之上.这篇文章就来复习一下简单数据类型,我会尽量从编程实践的角度来描述,下面代码运行环境为FireFox 14.0.1. 简单数据类型 简单数据类型 取值 Undefined undefined(只有一个值) Null null(只有一个值) Boolean true|false(只有两个值) Number 数值 St

JavaScript实现滚动栏效果的方法

  JavaScript实现滚动栏效果的方法         这篇文章主要介绍了JavaScript实现滚动栏效果的方法,涉及javascript操作html元素实现滚动的相关技巧,非常具有实用价值,需要的朋友可以参考下 本文实例讲述了JavaScript实现滚动栏效果的方法.分享给大家供大家参考.具体如下: ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34

JavaScript获得url查询参数的方法

  本文实例讲述了JavaScript获得url查询参数的方法.分享给大家供大家参考.具体实现方法如下: ? 1 2 3 4 5 6 7 8 9 10 function getQueryVariable(variable) { var query = window.location.search.substring(1); var vars = query.split("&"); for (var i=0;i<vars.length;i++) { var pair = v

JavaScript获得指定对象大小的方法

  本文实例讲述了JavaScript获得指定对象大小的方法.分享给大家供大家参考.具体如下: ? 1 2 3 4 5 6 7 8 9 10 11 function objectSize(the_object) { /* function to validate the existence of each key in the object to get the number of valid keys. */ var object_size = 0; for (key in the_objec