- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
目前我对 declare()
的实现感到好奇函数,它应该允许我使用原型(prototype)继承声明 javascript 类(或某种类型,因为 javascript 使用不同的对象模型,而不是经典的 OOP)。到目前为止,我发现了一些问题,我想知道一些人的意见和澄清(如果可能的话)。
这是一个“重现脚本”(简化以重现问题),可以在控制台中执行:
function namespace(){
if(arguments.length > 1){
var m, map, result;
for(m = 0; map = arguments[m], m < arguments.length; m++){
result = namespace(map);
}
return result;
}
var scope = window,
parts = arguments[0].split('.'),
part, p;
for(p = 0; part = parts[p], p < parts.length; p++){
if(typeof scope[part] === 'undefined'){
scope[part] = {};
}
scope = scope[part];
}
return scope;
}
function inherit(child, parent){
child.prototype = Object.create(parent);
child.prototype.constructor = child;
child.prototype.$parent = parent.prototype;
}
function mixin(target, source){
var value;
target = target || {};
if(typeof source == 'object'){
for(var property in source){
target[property] = source[property];
}
}
return target;
}
function extend(){
var mixins = Array.prototype.slice.call(arguments, 0),
object = mixins.shift() || {},
length = mixins.length,
m, mixin;
for(m = 0; mixin = mixins[m], m < length; mixin(object, mixin), m++);
return object;
}
function declare(config){
var map = config.object.split('.'),
name = map.pop(),
ns = namespace(map.join('.'));
ns[name] = function(){
this.constructor.apply(this, arguments);
};
if(config.parent){
if(typeof config.parent == 'string'){
config.parent = namespace(config.parent);
}
inherit(ns[name], config.parent);
}
if(config.mixins){
extend.apply(null, [ ns[name].prototype ].concat(config.mixins));
}
if(config.definition){
mixin(ns[name].prototype, config.definition);
}
}
declare({
object: 'Test.A',
definition: {
constructor: function(){
this.a = 1;
},
test: function(){
return this.a;
}
}
});
declare({
object: 'Test.B',
parent: 'Test.A',
definition: {
constructor: function(){
this.$parent.constructor.call(this);
this.b = 1;
},
test: function(){
return this.$parent.test.call(this) + this.b;
}
}
});
declare({
object: 'Test.C',
definition: {
x: 1
}
});
var a = new Test.A(),
b = new Test.B();
console.log('a.test() = ' + a.test());
console.log('b.test() = ' + b.test());
// var c = new Test.C();
declare()
应该合并 extend()
的功能, inherit()
和 mixin()
功能。作为参数,它需要一个 config
具有以下部分的对象:
#1 问题 是关于构造函数的:if config.definition
没有 constructor
方法,然后我得到 RangeError: Maximum call stack size exceeded
错误,这意味着我的“临时”构造函数
ns[name] = function(){
this.constructor.apply(this, arguments);
};
开始无限循环地调用自己。要重现,您可以取消注释 var c = new Test.C();
行。
问题: 我应该测试 config.definition
在 constructor
方法存在并注入(inject)一个空函数,其中没有 constructor
指定的方法来避免这种情况?是否有任何其他可能的方法而不会显着影响性能?
#2 问题 是关于调试的:当我尝试记录 a
时或 b
变量然后我得到 ns.(anonymous function){ ... }
在控制台中,这意味着我在执行“动态声明”时丢失了 namespace 和类/对象名称。
ns[name] = function(){ ... };
可能是没有名字的匿名函数的问题,所以浏览器会尝试保存最后的符号,这是赋值发生的地方。我希望有可能动态创建函数并为其定义名称,并找到了 this question , 建议使用 eval();
或 new Function(...)();
.
问题: 是否可以在没有任何 evUl()
的情况下保存命名空间和类名?魔法?
例如,这是我希望得到的:
namespace('X.Y');
X.Y.Z = function(){ this.a = 1 };
var test = new X.Y.Z();
console.log(test);
显示:
X.Y.Z {a: 1}
^^^^^
Literaly, what I want to achieve.
非常感谢您的帮助。谢谢。
最佳答案
Should I test config.definition on constructor method existence and inject an empty function, where there is no constructor method specified to avoid this? Is there any other possible approaches without significant performance impact?
是的,注入(inject)一个空函数作为构造函数实际上可以减少对性能的影响。
而不是 function(){this.constructor.apply(this, arguments);}
包装你应该只使用构造函数本身(除非你不确定它不返回一个对象):
ns[name] = config.definition && config.definition.constructor || function(){};
Is there any possibility to save namespace and classname without any eval() magic?
没有。您的调试器/检查器在这里用于描述实例的是 .name
of the constructor function .您不能使用命名函数设置另一个,并且它们的名称中不能包含点。
#3 问题 是您的继承
功能。而不是
child.prototype = Object.create(parent);
应该是
child.prototype = Object.create(parent.prototype);
关于javascript - "Good"实现 declare() 函数的实践,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22588982/
C语言sscanf()函数:从字符串中读取指定格式的数据 头文件: ?
最近,我有一个关于工作预评估的问题,即使查询了每个功能的工作原理,我也不知道如何解决。这是一个伪代码。 下面是一个名为foo()的函数,该函数将被传递一个值并返回一个值。如果将以下值传递给foo函数,
CStr 函数 返回表达式,该表达式已被转换为 String 子类型的 Variant。 CStr(expression) expression 参数是任意有效的表达式。 说明 通常,可以
CSng 函数 返回表达式,该表达式已被转换为 Single 子类型的 Variant。 CSng(expression) expression 参数是任意有效的表达式。 说明 通常,可
CreateObject 函数 创建并返回对 Automation 对象的引用。 CreateObject(servername.typename [, location]) 参数 serv
Cos 函数 返回某个角的余弦值。 Cos(number) number 参数可以是任何将某个角表示为弧度的有效数值表达式。 说明 Cos 函数取某个角并返回直角三角形两边的比值。此比值是
CLng 函数 返回表达式,此表达式已被转换为 Long 子类型的 Variant。 CLng(expression) expression 参数是任意有效的表达式。 说明 通常,您可以使
CInt 函数 返回表达式,此表达式已被转换为 Integer 子类型的 Variant。 CInt(expression) expression 参数是任意有效的表达式。 说明 通常,可
Chr 函数 返回与指定的 ANSI 字符代码相对应的字符。 Chr(charcode) charcode 参数是可以标识字符的数字。 说明 从 0 到 31 的数字表示标准的不可打印的
CDbl 函数 返回表达式,此表达式已被转换为 Double 子类型的 Variant。 CDbl(expression) expression 参数是任意有效的表达式。 说明 通常,您可
CDate 函数 返回表达式,此表达式已被转换为 Date 子类型的 Variant。 CDate(date) date 参数是任意有效的日期表达式。 说明 IsDate 函数用于判断 d
CCur 函数 返回表达式,此表达式已被转换为 Currency 子类型的 Variant。 CCur(expression) expression 参数是任意有效的表达式。 说明 通常,
CByte 函数 返回表达式,此表达式已被转换为 Byte 子类型的 Variant。 CByte(expression) expression 参数是任意有效的表达式。 说明 通常,可以
CBool 函数 返回表达式,此表达式已转换为 Boolean 子类型的 Variant。 CBool(expression) expression 是任意有效的表达式。 说明 如果 ex
Atn 函数 返回数值的反正切值。 Atn(number) number 参数可以是任意有效的数值表达式。 说明 Atn 函数计算直角三角形两个边的比值 (number) 并返回对应角的弧
Asc 函数 返回与字符串的第一个字母对应的 ANSI 字符代码。 Asc(string) string 参数是任意有效的字符串表达式。如果 string 参数未包含字符,则将发生运行时错误。
Array 函数 返回包含数组的 Variant。 Array(arglist) arglist 参数是赋给包含在 Variant 中的数组元素的值的列表(用逗号分隔)。如果没有指定此参数,则
Abs 函数 返回数字的绝对值。 Abs(number) number 参数可以是任意有效的数值表达式。如果 number 包含 Null,则返回 Null;如果是未初始化变量,则返回 0。
FormatPercent 函数 返回表达式,此表达式已被格式化为尾随有 % 符号的百分比(乘以 100 )。 FormatPercent(expression[,NumDigitsAfterD
FormatNumber 函数 返回表达式,此表达式已被格式化为数值。 FormatNumber( expression [,NumDigitsAfterDecimal [,Inc
我是一名优秀的程序员,十分优秀!