使用extend将对象添加到原型中
Using extend to add an object to a prototype
当我尝试将对象BaseNet
添加到IPv4Address.prototype
时,我得到一个错误。错误:
TypeError: Cannot read property 'ipInt' of undefined
就是没有意义。当我将对象复制到原型时,它的行为就像getter正在执行一样。有没有办法复制这个而不出现这样的错误?
var _s = require('underscore')
var BaseNet = {
get network(){
return new IPv4Address((this.ipInt & this.netmask.ipInt) >>> 0);
},
}
function IPv4Address (address){
this.ipInt = address
this.netmask = {}
this.netmask.ipInt = 255
}
_s.extend(IPv4Address.prototype,BaseNet)
//also fails with generic extend:
function extend(destination, source) {
for (var k in source) {
if (source.hasOwnProperty(k)) {
destination[k] = source[k];
}
}
return destination;
}
extend(IPv4Address.prototype,BaseNet)
第一次编辑也许这是我自己问题的答案。Resig对此有一个帖子,这个"修改"的扩展方法似乎做了我正在寻找的。有人能解释一下吗?这似乎是一个作用域问题,但我不明白为什么它的行为就像有人在扩展操作期间实际调用getter。
http://ejohn.org/blog/javascript-getters-and-setters/function extend(a,b) {
for ( var i in b ) {
var g = b.__lookupGetter__(i), s = b.__lookupSetter__(i);
if ( g || s ) {
if ( g )
a.__defineGetter__(i, g);
if ( s )
a.__defineSetter__(i, s);
} else
a[i] = b[i];
}
return a;
}
第二个编辑
所以我做了更多的实验,我想出了另外两种似乎有效的方法。一个使用前面发布的extend方法,另一个使用评论中指出的ECMA规范中的defineProperties方法。一个比另一个好吗?似乎"mixin"风格更适合我所寻找的,但对象。Create way也可以。
var BaseNet = {}
Object.defineProperties(BaseNet, {
"network":{
enumerable:true,
get: function (){return new IPv4Address((this.ipInt & this.netmask.ipInt) >>> 0)}
}
});
function IPv4Address (address){
this.ipInt = address
this.netmask = {}
this.netmask.ipInt = 255
}
IPv4Address.prototype = Object.create(BaseNet)
var ip = new IPv4Address(12345)
ip.netmask
或者,您也可以这样做:
var BaseNet = {}
Object.defineProperties(BaseNet, {
"network":{
enumerable:true,
get: function (){return new IPv4Address((this.ipInt & this.netmask.ipInt) >>> 0)}
}
});
function IPv4Address (address){
this.ipInt = address
this.netmask = {}
this.netmask.ipInt = 255
}
extend(IPv4Address.prototype,BaseNet)
var ip = new IPv4Address(12345)
ip.netmask
它不工作,因为同时扩展,getter被执行,在这一点上this.netmask
根本不是一个实例(没有创建的实例),但实际上undefined
,所以访问this.netmask.ipInt
抛出一个错误(你不能访问任何从undefined
或null
,它抛出一个错误在任何情况下)。
查看底层_.extend
代码:
_.extend = function(obj) {
each(slice.call(arguments, 1), function(source) {
for (var prop in source) {
// source[prop] is fetched, so getter is executed
if (source[prop] !== void 0) obj[prop] = source[prop];
}
});
return obj;
};
你可以自己迭代,用for in
循环和Object.defineProperty
复制getter " unchanged "。
至于你的编辑:那些__xxx__
函数是一个丑陋的方式来获得getter/setter函数而不执行它。通常,传递函数的工作方式类似于不带括号的someFunction
。但是,如果使用someGetter
访问getter,则会自动执行。
你发布的函数复制getter/setter而不执行它们:
function extend(a,b) {
for ( var i in b ) { // iterate over all properties
// get getter and setter functions
var g = b.__lookupGetter__(i), s = b.__lookupSetter__(i);
if ( g || s ) { // if there is a getter or setter
if ( g )
a.__defineGetter__(i, g); // copy getter to new object
if ( s )
a.__defineSetter__(i, s); // copy setter to new object
} else // if there is not getter nor setter
a[i] = b[i]; // just copy the value; nothing special
}
return a; // return the altered object
}
- 什么意思是“;向原型添加方法”;
- 向构造函数或原型添加属性之间的区别
- 何时向原型添加成员
- javascript原型-添加回调
- 向对象原型添加命名空间方法
- 无法将方法原型添加到 JavaScript 对象
- 向原型添加函数
- 向对象原型添加函数的正确方法
- 向对象原型添加函数会导致函数显示在所有“OBJ 中的 X”循环中
- 为什么在 javascript 中向数组原型添加方法会破坏 for 循环上的迭代
- 向函数、对象和原型添加属性
- 使用原型添加无限的输入字段
- 向Object/Number/String原型添加方法
- Uncaught TypeError:向Date原型添加函数时,这不是Date对象
- 如何通过原型添加Nodelist/HtmlColaction新方法
- 意外的令牌''在向原型添加功能时
- 通过原型添加方法
- 向JavaScript原型添加多个方法
- 为js对象的原型添加一个方法
- 向Javascript原型添加方法和向现有对象添加功能之间的区别是什么?