博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
《JavaScript应用程序设计》一一2.5 方法上下文
阅读量:6641 次
发布时间:2019-06-25

本文共 2555 字,大约阅读时间需要 8 分钟。

本节书摘来华章计算机出版社《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的开关可以响应来自用户的操作了。

转载地址:http://nvlvo.baihongyu.com/

你可能感兴趣的文章
RHCS(维护篇)
查看>>
let和const命令 — 学习ES6(一)
查看>>
shell脚本(二)
查看>>
nginx + tomcat配置https的两种方法
查看>>
21个挑战题,几杯咖啡的时间,来试试
查看>>
KVC KVO
查看>>
Oracle ODI 12c之多表联合查询以及定时任务设置
查看>>
设置KSH的自动补全和历史命令功能
查看>>
python--threading多线程总结
查看>>
我的友情链接
查看>>
PHP中数组的定义及声明实例
查看>>
批处理删除任意天之前的文件
查看>>
421 Home directory not available - aborting错误的解决方法
查看>>
我的友情链接
查看>>
我的友情链接
查看>>
js的发布/订阅模式
查看>>
Introduction To Neural Networks
查看>>
事件处理
查看>>
Android 中的 Service 全面总结(三)
查看>>
怎样利用strace调试
查看>>