javascript – For with with closure和function creation issues
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了javascript – For with with closure和function creation issues,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含3231字,纯文字阅读大概需要5分钟。
内容图文
我一直在尝试创建一个包装器函数,它接受一个对象(obj)的所有函数属性,并用另一个函数(p())包装它们.
这段代码说明了我的意思.
//Setup code
function p(input){
//do stuff
return new_output;
}
obj = {
prop1: function(){...},
prop2: function(){...},
prop3: function(){...}
}
//Here's the wrapper function
r = new R(obj);
//Expected behaviour
r.prop1(a1,a2); //Just like saying p(obj.prop1(a1,a2))
这是我对实施的尝试
function R (obj) {
for (var member in obj) {
//Mirrors obj's members
this[member] = function (args) {
var fn,inner_member = member;
//Convert to array for 'apply'
args = Array.prototype.slice.call(args,0);
fn = obj[member];
//Returns unexpected values, poo...
console.log(inner_member);
return p( fn.apply(fn,args) );
}
};
}
不幸的是,每当我运行r.prop1()时,控制台通过console.log返回错误的成员,“prop3”和obj [member]返回“obj.prop3”.一切都错了.
我认为这与闭包以及新创建的成员函数如何超出其范围有关.
我该如何解决?
编辑:David Flanagan的Javascript:The Definitive Guide在第8章第3节中直接回答了这个问题.那部分是关于闭包的,最后一个例子反映了我上面写的内容.理解我的问题的关键是函数在定义的同一范围链中调用.函数是对象和相关的范围链. AKA,关闭.
解决方法:
您在for循环中生成的函数引用的成员变量是相同的成员变量.
这是因为JavaScript没有块范围,只有函数范围.这是一个常见问题.
一种解决方案是在循环中调用函数,传入成员以使其成为新变量作用域的一部分.
function R (obj) {
// --------v---- use var to declare variables in order to avoid implicit globals
for (var member in obj) { // ...thanks to @CMS for the reminder.
createMember( member );
}
function createMember( mem ) {
//Mirrors obj's members
this[ mem ] = function (args) {
var fn,inner_member = mem;
//Conver to array for 'apply'
// Don't forget to use .call-----------v
args = Array.prototype.slice.call(args,0);
fn = obj[ mem ];
console.log(inner_member);
return p( fn.apply(fn,args) );
};
}
}
现在,循环中每次迭代中的成员值作为参数传递给单独的函数调用,每次都会创建一个新的变量作用域.
因为每个新函数都是每个唯一变量作用域的一部分,所以每个函数都引用一个不同的mem变量(或参数).
同一概念还有其他变体:
function R (obj) {
for (var member in obj) {
this[ member ] = createMember( member );
}
function createMember( mem ) {
//Mirrors obj's members
return function (args) {
var fn,inner_member = mem;
//Conver to array for 'apply'
// Don't forget to use .call-----------v
args = Array.prototype.slice.call(args,0);
fn = obj[ mem ];
console.log(inner_member);
return p( fn.apply(fn,args) );
};
}
}
这是相同的,除了它从要分配给此[member]的调用返回一个函数.同样的原则.
其他人更喜欢使用IIFE(立即调用的函数表达式)而不是命名函数.
function R (obj) {
for (var member in obj) {
(function( mem ) {
//Mirrors obj's members
this[ mem ] = function (args) {
var fn,inner_member = mem;
//Conver to array for 'apply'
// Don't forget to use .call----------------v
args = Array.prototype.slice.call(args,0);
fn = obj[ mem ];
console.log(inner_member);
return p( fn.apply(fn,args) );
};
})( member );
}
}
……虽然我认为它不太清楚,效率也低一点.
编辑:为成员变量添加了var以避免隐式全局变量.感谢@CMS.
编辑:将Array.prototype.slice(args,0)更改为Array.prototype.slice.call(args,0)
编辑:
这与任何问题无关,但是如果你所做的只是在包装器调用原始函数时传递参数,你就可以摆脱……
args = Array.prototype.slice.call(args,0);
并传递原始的参数对象:
return p( fn.apply( fn,arguments ) );
无需将其转换为数组.
内容总结
以上是互联网集市为您收集整理的javascript – For with with closure和function creation issues全部内容,希望文章能够帮你解决javascript – For with with closure和function creation issues所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。