- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在开发一个非常丑陋的库,它可以让你做一些奇怪的事情。有了图表,您可以以类似链的方式映射一组集合,并且当您更改在整个系统中更改的值。
当结束类型是 JS 原语时,问题就来了。
在我的例子中,在用值和对象制作图表后,我可以做这样的事情:
CHAIN.components[0].value = 20;
components
是使用 setter 和 getter 对图形节点进行过滤的函数。如果组件中只有一个节点被过滤,则用户设置的默认值将可用,而无需执行以下操作: CHAIN.components.value = 20;而是这样: CHAIN.components = 20;
现在的问题是节点除了默认值(在我的例子中是设置在 value
上)之外还可以有其他方法或属性。
我如何在不修改 Number.prototype 的情况下在 Number 对象上使用 setter 和 getter,因为 CHAIN.components
现在是一个 Number(如果它不是原语,我已经让它工作了一种不显眼的方式),但是当我想调用 CHAIN.components.func()
时出现问题,因为我必须将 func
附加到 Number.prototype每次我制作一个集合或获取 components
然后删除它。
对于完成这种行为,您有其他想法吗?
你想要代码,所以这里是:
/*jslint nomen: true, sloppy: true*/
GRID.modules.OHM || Object.extend(GRID.modules, ( function() {
var Node, Nodes, Ohm, num_proto = Number.prototype.__clone(), str_proto = String.prototype.__clone();
Node = function(uid) {
var UID = uid;
this.getUID = function() {
return UID;
};
};
Nodes = function() {
var stack = [];
this.add = function(id, val) {
var n = new Node(stack.length);
val.id = id;
Object.extend(n, val);
stack.push(n);
return n.getUID();
};
this.getById = function(id) {
return stack.filter(function(v) {
var a = id || v.id;
return (v.id === a);
});
};
this.getByUID = function(UID) {
return stack[UID];
};
this.get = function(callback) {
!Object.isString(callback) || ( callback = [callback]);
var f = Object.isFunction(callback) ? callback : (Object.isArray(callback) ? function(k) {
return (callback.indexOf(k.id) >= 0);
} : function(k) {
return true;
});
return stack.filter(f);
};
};
Ohm = function(n) {
var graph = n || (new Nodes()), filters = {}, __nodes = {}, addGS = function(obj, name, conf, binder) {
var alfa = {};
Object.extend(alfa, conf);
if (!alfa.get) {
alfa.get = function() {
var a = this.g.getById(this.p);
return a.length === 1 ? a[0] : a;
}.bind(binder);
} else {
alfa.get = alfa.get.bind(binder);
}
if (!alfa.set) {
alfa.set = function(value) {
this.g.getById(this.p).forEach(function(k) {
Object.extend(k, value);
return true;
});
}.bind(binder);
} else {
alfa.set = alfa.set.bind(binder);
}
Object.defineProperty(obj, name, alfa);
}, add = function(id, node) {
if (__nodes.hasOwnProperty(id)) {
addGS(__nodes, id, {
enumerable : true
}, {
t : this,
p : id,
g : graph
});
}
return graph.add(id, node || {});
};
Object.extend(this, {
add : function() {
add.apply(this, arguments);
},
map : function(name, f, that) {
var n = name, filterer = ['add', 'map', '__all'];
n = Object.isFunction(n) ? name.apply(that, arguments.slice(3)) : n;
if (filterer.indexOf(n.toLowerCase()) >= 0) {
console.log("You can't map over a basic property of object !!! Please read the freakin' manual.");
return null;
}
if (!filters.hasOwnProperty(n)) {
filters[n] = new Ohm(graph);
addGS(this, n, {
get : function() {
this.g.get(this.f).forEach(function(v, key, arr) {
var temp, binder;
if (arr.length !== 1) {
if (!this.filt.hasOwnProperty(v.id)) {
addGS(this.filt, v.id, {
set : function(value) {
this.t.g.getById(this.p).filter(this.t.f).forEach(function(k) {
Object.extend(k, value);
});
},
get : function() {
var a = this.t.g.getById(this.p).filter(this.t.f);
return a.length === 1 ? a[0] : a;
}
}, {
t : this,
p : v.id
});
(key !== arr.length - 1) || Object.extend(this.filt, this.g.get(this.f));
}
} else {
if (Object.isFunction(v.__new__)) {
v.__default = function() {
return Object.extend((new this.__new__(arguments)), this);
};
}
if (!Object.isUndefined(v.__default)) {
temp = this.filt;
this.filt = Object.isFunction(v.__default) ? v.__default.bind(v) : v.__default;
if (Object.isNumber(this.filt) || Object.isString(this.filt)) {
var prot = Object.isNumber(this.filt) ? Number : String;
for (var i in temp) {
if (temp.hasOwnProperty(i) && !prot.prototype.hasOwnProperty(i)) {
var bin = {
t : temp,
m : i,
p : prot,
};
Object.defineProperty(prot.prototype, i, {
set : function(value) {
Object.defineProperty(this.p.prototype, this.m, {
configurable : true, // defaults to false
writable : false,
value : 1
});
delete this.p.prototype[this.m];
this.t[this.m] = value;
}.bind(bin),
get : function() {
Object.defineProperty(this.p.prototype, this.m, {
configurable : true, // defaults to false
writable : false,
value : 1
});
delete this.p.prototype[this.m];
return this.t[this.m];
}.bind(bin),
enumerable : true,
configurable : true
});
}
}
} else {
Object.extend(this.filt, temp);
}
}
if (Object.isNumber(this.filt) || Object.isString(this.filt)) {
var prot = Object.isNumber(this.filt) ? Number : String;
for (var i in v) {
if (v.hasOwnProperty(i) && !prot.prototype.hasOwnProperty(i)) {
var bin = {
t : v,
m : i,
p : prot,
};
Object.defineProperty(prot.prototype, i, {
set : function(value) {
Object.defineProperty(this.p.prototype, this.m, {
configurable : true, // defaults to false
writable : false,
value : 1
});
delete this.p.prototype[this.m];
this.t[this.m] = value;
}.bind(bin),
get : function() {
Object.defineProperty(this.p.prototype, this.m, {
configurable : true, // defaults to false
writable : false,
value : 1
});
delete this.p.prototype[this.m];
return this.t[this.m];
}.bind(bin),
enumerable : true,
configurable : true
});
}
}
} else {
Object.extend(this.filt, v);
}
}
}, this);
return this.filt;
},
set : function(value) {
this.g.get(this.f).forEach(function(k) {
Object.extend(k, value);
});
}
}, {
t : this,
f : f,
g : graph,
filt : filters[n]
});
}
}
}, true, true);
addGS(this, '__all', {
get : function() {
var a = this.g.getById();
Object.extend(__nodes, a.length === 1 ? a[0] : a);
return __nodes;
},
enumerable : true
}, {
t : this,
p : null,
g : graph
});
};
window['Ω'] = Ohm;
return {
OHM : Ohm,
};
}()));
现在是演示:
var c = new Ω();
c.add('ann', {
__default : 58,
blah : 98,
ceva : function()
{
console.log('asd');
}
});
c.add('ann2',{
__default: function(){
console.log('hello');
},
abc: 78,
dce: function(){
console.log(' world');
}
};
c.add('b2', {
__new__ : function() {
this.init = function() {
this.id = 86;
};
this.mer = function() {
console.log(this);
};
},
els : 'asadar'
});
c.map('b2', function(k) {
return k.id === 'b2';
});
c.map('ann', function(k) {
return k.id === 'ann';
});
c.map('ann2', function(k) {
return k.id === 'ann2';
});
console.log(c.ann); // returns 58 ( the __default value )
console.log(c.ann.blah); // returns 98
console.log(c.ann.blah.blah); // undefined
console.log(c.ann2); // function()
c.ann2(); // prints out 'hello'
c.ann2.cde(); // prints out 'world'
c.ann2 = 60;
console.log(c.ann2); // 60
console.log(c.ann2.cde()); // prints out 'world'
此代码有效,但我必须使用 Number 或 String 原型(prototype)的部分让我很困扰。您有其他方法吗?
原因是要做一些有人说可以用 PHP 而不是 JS 完成的事情,这个人最近一直在和我一起研究 WebGL 着色器并且讨厌他必须编写 700 行代码才能使用多种效果结合FBO 而不是 100,这会让他使用类似的工具,比如用 PHP 编写的工具。所以是的,我知道原始原型(prototype)上的访问器是一个 hack,但是如果链端对象是原始对象,我如何才能在不必使用 valueOf 的情况下使它与众不同?
最佳答案
好的,现在我已经阅读了附加的代码(但无法完全理解)。缺少一些评论,但我不会为此提示,我自己的代码并没有更好,因为我不希望任何人阅读或理解它们:-)
你是对的,你扩展原生原型(prototype)的部分很可怕。据我了解,您在返回数字/字符串之前在 Number 或 String 原型(prototype)上定义了一个访问器属性。在获取和设置时,访问器属性都被数据属性(???)覆盖,然后在存储/返回值之前删除整个属性。这似乎是允许原始值自定义属性的聪明技巧,但是:
this
值作为查找表中的键来降低它(以区分 (5).x
和 (3).x
),但仍然无法完全避免。如果您真的需要这个(我仍然不明白您的理由),我会使用带有查找表的变体。它应该减少冲突(不确定你的代码如何处理它们),不会改变它们定义的访问器属性,因此更持久(尽管它可能会泄漏):
// Let's call this
// PRIMITIVE PROXIES
// as they proxy real objects behind primitive values
var proxy = _.map( { // some map that works on Objects
string: String.prototype,
number: Number.prototype
}, function closure(type, proto) {
var table = {};
function setupProperty(prop) {
if (prop in proto) return; // ah, we already proxied this kind of object
Object.defineProperty(proto, prop, {
configurable:true, // for deleting
get: function getter() {
// "this" is the primitive value
if (!this in table)
return undefined;
return table[this][prop]; // get prop from obj
},
set: function setter(val) {
if (this in table)
table[this][prop] = val; // pass val to obj
}
});
}
return {
create: function createProxy(prim, obj) {
if (prim in table) // we already did create a proxy on this primitive
return; // let's abort. You might continue to overwrite
table[prim] = obj;
Object.getOwnPropertyNames(obj).forEach(setupProperty);
return prim; // the new "proxy"
},
move: function moveName(from, to) {
if (to in table) return false;
table[to] = table[from];
delete table[from];
return true;
}
};
});
proxy.create = function(prim, obj) {
return proxy[typeof prim].create(prim, obj);
};
proxy.move = function(from, to) {
return proxy[typeof from].create(from, to);
};
// USAGE:
// proxy.create works just like Object.extend
> var c = {ann: 58},
> o = {blah: 98};
> proxy.create(c.ann, o);
> 58..blah
98
> c.ann.blah
98
> (58).blah = 60;
> o
{blah: 60}
> var num = c.ann; // 58
> c.ann.blah = function(){return "Hello"};
> num.blah()
"Hello"
> proxy.move(c.ann, c.ann = 78);
> c.ann
78
> (58).blah
undefined
> c.ann.blah()
"Hello"
> // getters/setters for properties are global:
> c.ann.blub = "something"; // does not work, there is no getter
> c.ann.blub
undefined
> proxy.create(58, {blub: "foo"})
> c.ann.blub // still returns
undefined
> c.ann.blub = "bar"; // but can be set now
> (58).blub + (78).blub
"foobar"
> // infinite lookup loops are possible:
> proxy.create("loop", {x:"loop"});
> "loop" === "loop".x
true
> "loop".x.x.x.….x
"loop"
但是,有一件事是您永远无法解决的:
Unlike objects, primitive values are not unique; they have no identity.
你永远无法区分 c.ann
和 58
,或者 “loop”
和 “loop”.x
,因此两者都将具有或不具有属性。这不是构建 API 的好前提。
所以,我还是推荐使用Number
和String
对象。您不需要对它们进行子类化(如我之前的回答所示),因为它们似乎没有 (m) 任何方法,因此您可以轻松构建它们:
c.ann = new Number(58);
c.ann.blah = 98;
return c;
除了 typeof
运算符之外,应该几乎没有区别。您能否添加更多使用 __default
值的示例?
but how can I make it different without having to use valueOf if the chain end object is a primitive?
要回答这个简单的问题:那个人是对的,如果不破解 native 原型(prototype),就无法在 JavaScript 中完成。你是对的,这个黑客非常丑陋:-)
关于javascript - 扩展基元而不对其进行原型(prototype)设计,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13606375/
关闭。这个问题需要更多focused .它目前不接受答案。 想改善这个问题吗?更新问题,使其仅关注一个问题 editing this post . 4年前关闭。 Improve this questi
.NET 框架:4.5.1 我在 Blend for visual studio 2015 中遇到一个奇怪的错误,我找不到它的来源。 如果我在 VS 中打开我的 WPF 解决方案,它会加载并运行良好。
我经常遇到这样的问题,与 Hierarchical RESTful URL design 非常相似 假设该服务仅提供用户上传文档。 POST, GET /accounts PUT, DELETE /a
在 Rails 应用程序中,我使用 devise 来管理我的用户,而我用来销毁 session 的链接不再有效。它正在工作,现在我添加了事件管理员,但没有。 我的链接是 :delete, :clas
我已经坚持了超过 24 小时,试图按照此处发布的其他解决方案进行操作,但我无法使其正常工作。我是 Rails 新手,需要帮助! 我想让我的/users/edit 页面正常工作,以便我可以简单地更改用户
Devise 在以下情况下不会使用户超时: 用户登录,关闭选项卡,然后在超时 + X 分钟内重新访问该 URL。用户仍处于登录状态。 如果选项卡已打开并且稍后刷新/单击,则超时可以正常工作。这意味着
我想使用这样的 slider 我希望该 slider 根据提供给它的值进行相应调整。到目前为止,我只能应用具有渐变效果的背景,但无法获得这种效果。请通过提供样式代码来帮助我。
您应该为每种方法创建一个请求/响应对象,还是应该为每个服务创建一个? 如果我在所有方法中使用它,我的服务请求对象中将只有 5 个不同的东西,因为我对几乎所有方法使用相同的输入。 响应对象将只有一个字典
我正在尝试在 REST 中对实体的附件进行建模。假设一个缺陷实体可以附加多个附件。每个附件都有描述和一些其他属性(上次修改时间、文件大小...)。附件本身是任何格式的文件(jpeg、doc ...)
我有以下表格: Blogs { BlogName } BlogPosts { BlogName, PostTitle } 博客文章同时建模一个实体和一个关系,根据 6nf(根据第三个宣言)这是无效的。
如果 A 类与 B、C 和 D 类中的每一个都有唯一的交互,那么交互的代码应该在 A 中还是在 B、C 和 D 中? 我正在编写一个小游戏,其中许多对象可以与其他对象进行独特的交互。例如,EMP点击
关于如何记住我与 Omniauth 一起工作似乎有些困惑。 根据这个wiki ,您需要在 OmniauthCallbacksController 中包含以下内容: remember_me(user)
设计问题: 使用 非线程安全 组件(集合,API,...)在/带有 多线程成分 ... 例子 : 组件 1 :多线程套接字服务器谁向消息处理程序发送消息... 组件 2 :非线程安全 消息处理程序 谁
我们目前正在设计一个 RESTful 应用程序。我们决定使用 XML 作为我们的基本表示。 我有以下关于在 XML 中设计/建模应用程序数据的问题。 在 XML 中进行数据建模的方法有哪些?从头开始然
我正在设计一个新的 XSD 来从业务合作伙伴那里获取积分信息。对于每笔交易,合作伙伴必须提供至少一种积分类型的积分值。我有以下几点:
设计支持多个版本的 API 的最佳方法是什么。我如何确保即使我的数据架构发生更改(微小更改),我的 api 的使用者也不会受到影响?任何引用架构、指南都非常有用。 最佳答案 Mark Nottingh
关闭。这个问题是opinion-based 。目前不接受答案。 想要改进这个问题吗?更新问题,以便 editing this post 可以用事实和引文来回答它。 . 已关闭 4 年前。 Improv
我想用 php 创建一个网站,其工作方式与 https://www.bitcoins.lc/ 相同。确实,就每个页面上具有相同布局但内容会随着您更改链接/页面而改变而言,我如何在 php 中使用lay
我有一个关于编写 Swing UI 的问题。如果我想制作一个带有某些选项的软件,例如在第一个框架上,我有三个按钮(新建、选项、退出)。 现在,如果用户单击新按钮,我想将框架中的整个内容更改为其他内容。
我正在尝试找出并学习将应用程序拥有的一堆Docker容器移至Kubernetes的模式和最佳实践。诸如Pod设计,服务,部署之类的东西。例如,我可以创建一个其中包含单个Web和应用程序容器的Pod,但
我是一名优秀的程序员,十分优秀!