我认为这很简单,
是否有一种简单的方法为属性添加辅助名称(我认为这是特定于字符串的 - 我不确定),即。,
c = length // this line pseudo code
'hello world'.length // returns 11
'hello world'.c // this line is pseudo code, meant to return 11
在上面的示例中,为属性长度创建了一个别名。这可以用JavaScript吗?
答案 0 :(得分:37)
<强> 1。使用括号表示法
使用bracket notation,您可以像这样访问该属性:
'hello world'[c]
如果'hello world'.length
为c
为字符串,则与'length'
相同。
var c = 'length';
console.log('hello world'[c]);
&#13;
唯一的区别是该属性是一个字符串。括号表示法是属性访问者。
<强> 2。使用Object.defineProperty()
现在,如果你想要一个别名:
Object.defineProperty(String.prototype, 'c', {
get: function() {
return this.length;
}
});
console.log("hello world".c);
&#13;
以上使用Object.defineProperty
来定义现有对象String的prototype
对象的属性。这样,字符串的所有实例都将具有此新属性。根据文件:
Object.defineProperty()
方法直接在对象上定义新属性,或修改对象上的现有属性,并返回该对象。<强>语法强>
Object.defineProperty(obj, prop, descriptor)
obj
是要修改的对象,prop
是新属性或现有属性,descriptor
是新属性或现有属性的描述符。
因此,上面定义了对象String.prototype
的属性,名称为c
。它的描述符是一个get函数,它返回this
的长度。在上面的示例中,this
引用字符串,因此它返回字符串的长度。您可以阅读有关getter here的更多信息。
也可以通过更改为适用的原型(obj
)来定义更多类型,例如使用Object.prototype
。但是,这有潜在的问题,因为尝试在没有长度属性的对象上返回this.length
将返回undefined,如here所示。您也可以使用Object.defineProperties
一次定义多个属性。
答案 1 :(得分:6)
为了扩展@ AndrewLi的答案,你可以使用Object.defineProperty()
做一些别名的事情。
我会将它们编写为将源对象与属性相关联的函数, sProp 以及带有属性的目标对象 tProp 即可。源和目标可以是同一个对象(允许属性成为同一对象上另一个属性的别名),但这不是必需的。此外,源(或目标)可以是原型(如Object.prototype,String.prototype等)。
这个不是别名,也不是Object.defineProperty()
。目标被指定为源的 VALUE ,而不是对其的引用。这意味着当源更改时,目标不会。
function assign(target, tProp, source, sProp) {
target[tProp] = source[sProp];
return target;
}
let myTarget = {}
let mySource = {b: 12}
myTarget = assign(myTarget, 'a', mySource, 'b')
// "alias" was assigned source value
console.log('"alias":',myTarget.a) // 12
// changes to source independent of "alias"
mySource.b = 13
console.log("source:", mySource.b) // 13
console.log('"alias":', myTarget.a) // still 12
当属性定义没有setter时,它实际上是一个只读值。对source属性的更改将反映在别名中;但是,您无法设置别名的值。
function read(target, tProp, source, sProp){
Object.defineProperty(target, tProp, {
enumerable: true,
configurable: true,
get(){
return source[sProp];
}
})
return target;
}
let myTarget = {}
let mySource = {b: 12}
myTarget = read(myTarget, 'a', mySource, 'b')
// Alias gets value from source
console.log("alias:", myTarget.a) // 12
// No setter effectively means read-only
myTarget.a = 15
console.log("alias:", myTarget.a) // 12
// Changes to source are seen in target
mySource.b = 15
console.log("source:", mySource.b) //15
console.log("target:", myTarget.a) //15
此别名修改上面的只读版本,以便在设置别名(目标)属性时设置source属性。通过这种方式,源和目标始终保持同步。
function sync(target, tProp, source, sProp){
Object.defineProperty(target, tProp, {
enumerable: true,
configurable: true,
get(){
return source[sProp];
},
set(value){
source[sProp] = value;
}
})
return target;
}
let myTarget = {}
let mySource = {b: 12}
myTarget = sync(myTarget, 'a', mySource, 'b')
// Alias gets value from source
console.log("alias:", myTarget.a) // 12
// Changing alias' value modifies the source
myTarget.a = 15
console.log("alias:", myTarget.a) // 15
console.log("source:", mySource.b) // 15
// Changing source modifies alias still
mySource.b = 20
console.log("source:", mySource.b) // 20
console.log("alias:", myTarget.a) // 20
这允许您默认别名/目标值,直到另行更新。与只读的情况不同,您可以更改别名/目标值,但与同步不同,当您更改别名时,您不会更新源 - 而是别名变为常规值。
function setDefault(target, tProp, source, sProp){
Object.defineProperty(target, tProp, {
enumerable: true,
configurable: true,
get(){
return source[sProp];
},
set(value){
delete target[tProp];
target[tProp] = value;
}
})
return target;
}
let myTarget = {}
let mySource = {b: 12}
myTarget = setDefault(myTarget, 'a', mySource, 'b')
// Alias gets value from source
console.log('alias:', myTarget.a) // 12
// Changing source modifies alias still
mySource.b = 15
console.log('source:', mySource.b) // 15
console.log('alias:', myTarget.a) // 15
// Changing alias' value DOES NOT modify source
myTarget.a = 20
console.log("alias:", myTarget.a) // 20
console.log("source:", mySource.b) // 15
// The relationship between source and alias is BROKEN
mySource.b = 100
console.log("source:", mySource.b) // 100
console.log("alias:", myTarget.a) // 20