Javascript 向函数添加自定义属性
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/8588563/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Adding custom properties to a function
提问by Przemek
Searching for appropriate answer proved difficult because of the existence of many other problems related to my keywords, so I'll ask this here.
由于存在与我的关键字相关的许多其他问题,因此很难找到合适的答案,所以我会在这里提问。
As we know, functions in javascript are objects and they have their own properties and methods (more properly, function istances, inherited from Function.prototype).
正如我们所知,javascript 中的函数是对象,它们有自己的属性和方法(更准确地说,函数实例,继承自 Function.prototype)。
I was considering adding custom properties for one function (method), let's skip the "why?" part and go straight to the code:
我正在考虑为一个函数(方法)添加自定义属性,让我们跳过“为什么?” 部分并直接进入代码:
var something = {
myMethod: function () {
if (something.myMethod.someProperty === undefined) {
something.myMethod.someProperty = "test";
}
console.log(something.myMethod);
}
}
When inspected with Firebug's DOM explorer, the property is defined as expected. However, as I don't consider myself a javascript expert, I have the following questions:
使用 Firebug 的 DOM 资源管理器检查时,该属性按预期定义。但是,由于我不认为自己是 javascript 专家,因此我有以下问题:
- Can this method be considered "proper" and standards compliant? It works in Firefox but there are many things working as expected in web browsers and aren't by any means standards.
- Is this kind of altering objects by adding new properties to them a good practice?
- 这种方法可以被认为是“正确的”并且符合标准吗?它可以在 Firefox 中运行,但是在 Web 浏览器中,有很多东西可以按预期运行,而且无论如何都不是标准。
- 这种通过向对象添加新属性来改变对象的做法是一种好习惯吗?
采纳答案by nnnnnn
It's a little bit difficult to give a very meaningful answer to your question, because you've sort of said "Here is my solution, is it OK?" without explaining what problem you are trying to solve (you even said explicitly that you are not going to explain the "why"). Your code looks to be valid JavaScript that will run, but it also looks like a less than optimal way of doing things.
对你的问题给出一个非常有意义的答案有点困难,因为你有点说“这是我的解决方案,可以吗?” 没有解释您要解决的问题(您甚至明确表示您不会解释“为什么”)。您的代码看起来是可以运行的有效 JavaScript,但它看起来也不是最佳的做事方式。
If you explain what you actually want to achieve you may get some good suggestions on better ways to structure your code. Still, I'll give you some kind of answer:
如果你解释了你真正想要实现的目标,你可能会得到一些关于更好的代码结构方式的好建议。不过,我会给你一些答案:
Can this method be considered "proper" and standards compliant? It works in Firefox but there are many things working as expected in web browsers and aren't by any means standards.
这种方法可以被认为是“正确的”并且符合标准吗?它可以在 Firefox 中运行,但是在 Web 浏览器中,有很多东西可以按预期运行,而且无论如何都不是标准。
Functions are objects (as you've said), and thus it is possible to add properties to them. This isn't really a standards issue as such in that it is a core part of JavaScript that all browsers support.
函数是对象(如您所说),因此可以向它们添加属性。这并不是一个真正的标准问题,因为它是所有浏览器都支持的 JavaScript 的核心部分。
Is this kind of altering objects by adding new properties to them a good practice?
这种通过向对象添加新属性来改变对象的做法是一种好习惯吗?
It's your object, you can add whatever properties you like. The whole point of objects is that they have properties that you can manipulate. I can't really envisage a way of using objects that doesn't involve altering them, including adding, deleting and updating properties and methods.
这是你的对象,你可以添加任何你喜欢的属性。对象的全部意义在于它们具有您可以操作的属性。我真的无法设想一种不涉及更改对象的使用方法,包括添加、删除和更新属性和方法。
Having said that, to me it doesn't really make sense to add properties to the myMethod
function, it would be more usual to add other properties to your something
object (your myMethod
function would, if called correctly, have access to the other properties of something
via the this
keyword).
话虽如此,对我来说,向myMethod
函数添加属性并没有真正意义,向something
对象添加其他属性会更常见(myMethod
如果调用正确,您的函数将可以something
通过this
关键词)。
If you are using a function as a constructorit typically makes sense to add methodsto the associated prototype and add (non-method) properties to each instance, but you can do either or both the other way when appropriate. (Noting that a "method" is essentially just a property that happens to reference a function.)
如果您正在使用一个函数作为构造它通常是有意义的添加方法到相关的原型,并添加(非法)性能每个实例,但你可以做一个或两个其他方式时适当。(请注意,“方法”本质上只是一个恰好引用函数的属性。)
The specific code you have shown doesn't add properties, it tests whether the someProperty
property alreadyexists and if so assigns it a new value.
您显示的特定代码不会添加属性,它会测试该someProperty
属性是否已经存在,如果存在,则为其分配一个新值。
You might benefit from reading some articles such as these at MDN:
您可能会从 MDN 上的一些文章中受益:
回答by John Slegers
First of all, it's important to realise that standard function properties (arguments, name, caller & length) cannot be overwritten. So, forget about adding a property with that name.
首先,重要的是要意识到标准函数属性(参数、名称、调用者和长度)不能被覆盖。因此,忘记添加具有该名称的属性。
Adding your own custom properties to a function can be done in different ways that should work in every browser.
将您自己的自定义属性添加到函数可以通过不同的方式完成,这些方式应该适用于每个浏览器。
Adding your own custom properties to a function
将您自己的自定义属性添加到函数
Way 1 :adding properties while running the function :
方式1:在运行函数时添加属性:
var doSomething = function() {
doSomething.name = 'Tom';
doSomething.name2 = 'John';
return 'Beep';
};
console.log('doSomething.name : ' + doSomething.name);
console.log('doSomething.name2 : ' + doSomething.name2);
console.log('doSomething() : ' + doSomething());
console.log('doSomething.name : ' + doSomething.name);
console.log('doSomething.name2 : ' + doSomething.name2);
Output :
输出 :
doSomething.name :
doSomething.name2 : undefined
doSomething() : Beep
doSomething.name :
doSomething.name2 : John
Way 1(alternate syntax) :
方式 1(替代语法):
function doSomething() {
doSomething.name = 'Tom';
doSomething.name2 = 'John';
return 'Beep';
};
console.log('doSomething.name : ' + doSomething.name);
console.log('doSomething.name2 : ' + doSomething.name2);
console.log('doSomething() : ' + doSomething());
console.log('doSomething.name : ' + doSomething.name);
console.log('doSomething.name2 : ' + doSomething.name2);
Output :
输出 :
doSomething.name : doSomething
doSomething.name2 : undefined
doSomething() : Beep
doSomething.name : doSomething
doSomething.name2 : John
Way 1(second alternate syntax) :
方式 1(第二种替代语法):
var doSomething = function f() {
f.name = 'Tom';
f.name2 = 'John';
return 'Beep';
};
console.log('doSomething.name : ' + doSomething.name);
console.log('doSomething.name2 : ' + doSomething.name2);
console.log('doSomething() : ' + doSomething());
console.log('doSomething.name : ' + doSomething.name);
console.log('doSomething.name2 : ' + doSomething.name2);
Output :
输出 :
doSomething.name : f
doSomething.name2 : undefined
doSomething() : Beep
doSomething.name : f
doSomething.name2 : John
A problem with this strategy is that you need to run your function at least once to assign the properties. For many functions, that's obviously not what you want. So let's consider the other options.
此策略的一个问题是您需要至少运行一次函数来分配属性。对于许多功能,这显然不是您想要的。因此,让我们考虑其他选项。
Way 2 :adding properties after defining the function :
方式二:定义函数后添加属性:
function doSomething() {
return 'Beep';
};
doSomething.name = 'Tom';
doSomething.name2 = 'John';
console.log('doSomething.name : ' + doSomething.name);
console.log('doSomething.name2 : ' + doSomething.name2);
console.log('doSomething() : ' + doSomething());
console.log('doSomething.name : ' + doSomething.name);
console.log('doSomething.name2 : ' + doSomething.name2);
Output :
输出 :
doSomething.name : doSomething
doSomething.name2 : John
doSomething() : Beep
doSomething.name : doSomething
doSomething.name2 : John
Now, you don't need to run your function first before you're able to access your properties. However, a disadvantage is that your properties feel disconnected from your function.
现在,您无需先运行您的函数即可访问您的属性。但是,一个缺点是您的属性感觉与您的功能脱节。
Way 3 :wrap your function in anonymous function :
方式 3:将您的函数包装在匿名函数中:
var doSomething = (function(args) {
var f = function() {
return 'Beep';
};
for (i in args) {
f[i] = args[i];
}
return f;
}({
'name': 'Tom',
'name2': 'John'
}));
console.log('doSomething.name : ' + doSomething.name);
console.log('doSomething.name2 : ' + doSomething.name2);
console.log('doSomething() : ' + doSomething());
console.log('doSomething.name : ' + doSomething.name);
console.log('doSomething.name2 : ' + doSomething.name2);
Output :
输出 :
doSomething.name :
doSomething.name2 : John
doSomething() : Beep
doSomething.name :
doSomething.name2 : John
Wrapping your function in an anonymous function, you can collect your attributes into an object and use a loop to add those attributes one-by-one within the anonymous function. That way, your attributes feel more connected to your function. This technique is also very useful for when your attributes need to be copied from an existing object. A disadvantage, however, is that you can only add multiple attributes at the same time when you define your function. Also, it doesn't exactly result in DRY code if adding properties to a function is something you want to do often.
将您的函数包装在匿名函数中,您可以将您的属性收集到一个对象中,并使用循环在匿名函数中逐一添加这些属性。这样,您的属性就会与您的功能更加相关。当需要从现有对象复制属性时,此技术也非常有用。但是,一个缺点是您只能在定义函数时同时添加多个属性。此外,如果向函数添加属性是您经常想要做的事情,它不会完全导致 DRY 代码。
Way 4 :add an 'extend' function to your function, that adds the properties of an object to itself one by one :
方式 4:向函数添加“扩展”函数,将对象的属性一一添加到自身:
var doSomething = function() {
return 'Beep';
};
doSomething.extend = function(args) {
for (i in args) {
this[i] = args[i];
}
return this;
}
doSomething.extend({
'name': 'Tom',
'name2': 'John'
});
console.log('doSomething.name : ' + doSomething.name);
console.log('doSomething.name2 : ' + doSomething.name2);
console.log('doSomething() : ' + doSomething());
console.log('doSomething.name : ' + doSomething.name);
console.log('doSomething.name2 : ' + doSomething.name2);
Output :
输出 :
doSomething.name :
doSomething.name2 : John
doSomething() : Beep
doSomething.name :
doSomething.name2 : John
This way, you can extend multiple properties and/or copy properties from another project at any time. Again, however, your code isn't DRY if this is something you do more often.
这样,您可以随时扩展多个属性和/或从另一个项目复制属性。但是,如果这是您经常执行的操作,那么您的代码也不是 DRY。
Way 5 :Make a generic 'extend' function :
方式 5:制作一个通用的“扩展”功能:
var extend = function(obj, args) {
if (Array.isArray(args) || (args !== null && typeof args === 'object')) {
for (i in args) {
obj[i] = args[i];
}
}
return obj;
}
var doSomething = extend(
function() {
return 'Beep';
}, {
'name': 'Tom',
'name2': 'John'
}
);
console.log('doSomething.name : ' + doSomething.name);
console.log('doSomething.name2 : ' + doSomething.name2);
console.log('doSomething() : ' + doSomething());
console.log('doSomething.name : ' + doSomething.name);
console.log('doSomething.name2 : ' + doSomething.name2);
Output :
输出 :
doSomething.name :
doSomething.name2 : John
doSomething() : Beep
doSomething.name :
doSomething.name2 : John
A genetic extend function allows for a more DRY approach, allowing you to add the object or any project to any other object.
遗传扩展功能允许采用更 DRY 的方法,允许您将对象或任何项目添加到任何其他对象。
Way 6 :Create an extendableFunction object and use it to attach an extend function to a function :
方式 6:创建一个 extendableFunction 对象并使用它来将扩展函数附加到函数:
var extendableFunction = (function() {
var extend = function(args) {
if (Array.isArray(args) || (args !== null && typeof args === 'object')) {
for (i in args) {
this[i] = args[i];
}
}
return this;
};
var ef = function(v, obj) {
v.extend = extend;
return v.extend(obj);
};
ef.create = function(v, args) {
return new this(v, args);
};
return ef;
})();
var doSomething = extendableFunction.create(
function() {
return 'Beep';
}, {
'name': 'Tom',
'name2': 'John'
}
);
console.log('doSomething.name : ' + doSomething.name);
console.log('doSomething.name2 : ' + doSomething.name2);
console.log('doSomething() : ' + doSomething());
console.log('doSomething.name : ' + doSomething.name);
console.log('doSomething.name2 : ' + doSomething.name2);
Output :
输出 :
doSomething.name :
doSomething.name2 : John
doSomething() : Beep
doSomething.name :
doSomething.name2 : John
Rather than using a generic 'extend' function, this technique allows you to generate functions that have an 'extend' method attached to it.
这种技术不是使用通用的“扩展”函数,而是允许您生成附加了“扩展”方法的函数。
Way 7 :Add an 'extend' function to the Function prototype :
方式 7:在函数原型中添加一个“扩展”函数:
Function.prototype.extend = function(args) {
if (Array.isArray(args) || (args !== null && typeof args === 'object')) {
for (i in args) {
this[i] = args[i];
}
}
return this;
};
var doSomething = function() {
return 'Beep';
}.extend({
name : 'Tom',
name2 : 'John'
});
console.log('doSomething.name : ' + doSomething.name);
console.log('doSomething.name2 : ' + doSomething.name2);
console.log('doSomething() : ' + doSomething());
console.log('doSomething.name : ' + doSomething.name);
console.log('doSomething.name2 : ' + doSomething.name2);
Output :
输出 :
doSomething.name :
doSomething.name2 : John
doSomething() : Beep
doSomething.name :
doSomething.name2 : John
A great advantage to this technique is that it makes adding new properties to a function very easy and DRY as well as completely OO. Also, it's pretty memory friendly. A downside, however, is that it's not very future proof. In case future browsers ever add a native 'extend' function to the Function prototype, this that could break your code.
这种技术的一个巨大优势是,它使向函数添加新属性非常容易、DRY 以及完全面向对象。此外,它对内存非常友好。然而,一个缺点是它不是未来的证明。如果未来的浏览器向 Function 原型中添加了原生的“扩展”函数,这可能会破坏您的代码。
Way 8 :Run a function recursively once and then return it :
方式 8:递归地运行一个函数一次然后返回它:
var doSomething = (function f(arg1) {
if(f.name2 === undefined) {
f.name = 'Tom';
f.name2 = 'John';
f.extend = function(args) {
if (Array.isArray(args) || (args !== null && typeof args === 'object')) {
for (i in args) {
this[i] = args[i];
}
}
return this;
};
return f;
} else {
return 'Beep';
}
})();
console.log('doSomething.name : ' + doSomething.name);
console.log('doSomething.name2 : ' + doSomething.name2);
console.log('doSomething() : ' + doSomething());
console.log('doSomething.name : ' + doSomething.name);
console.log('doSomething.name2 : ' + doSomething.name2);
Output :
输出 :
doSomething.name : f
doSomething.name2 : John
doSomething() : Beep
doSomething.name : f
doSomething.name2 : John
Run a function once and have it test whether one of its properties is set. If not set, set the properties and return itself. If set, execute the function. If you include an 'extend' function as one of the properties, you can later execute that to add new properties.
运行一次函数并让它测试是否设置了其属性之一。如果未设置,则设置属性并返回自身。如果设置,则执行该功能。如果您将“扩展”函数作为属性之一包含在内,您可以稍后执行该函数以添加新属性。
Adding your own custom properties to an object
将您自己的自定义属性添加到对象
In spite of all these options, I would nevertheless recommend against adding properties to a function. It's much better to add properties to objects!
尽管有所有这些选项,但我仍然建议不要向函数添加属性。为对象添加属性要好得多!
Personally, I prefer the singleton classes with the following syntax.
就个人而言,我更喜欢具有以下语法的单例类。
var keyValueStore = (function() {
return {
'data' : {},
'get' : function(key) { return keyValueStore.data[key]; },
'set' : function(key, value) { keyValueStore.data[key] = value; },
'delete' : function(key) { delete keyValueStore.data[key]; },
'getLength' : function() {
var l = 0;
for (p in keyValueStore.data) l++;
return l;
}
}
})();
An advantage to this syntax is that it allows for both public and private variables. For example, this is how you make the 'data' variable private :
这种语法的一个优点是它允许公共和私有变量。例如,这是将“数据”变量设为私有的方式:
var keyValueStore = (function() {
var data = {};
return {
'get' : function(key) { return data[key]; },
'set' : function(key, value) { data[key] = value; },
'delete' : function(key) { delete data[key]; },
'getLength' : function() {
var l = 0;
for (p in data) l++;
return l;
}
}
})();
But you want multiple datastore instances, you say? No problem!
但是你想要多个数据存储实例,你说?没问题!
var keyValueStore = (function() {
var count = -1;
return (function kvs() {
count++;
return {
'data' : {},
'create' : function() { return new kvs(); },
'count' : function() { return count; },
'get' : function(key) { return this.data[key]; },
'set' : function(key, value) { this.data[key] = value; },
'delete' : function(key) { delete this.data[key]; },
'getLength' : function() {
var l = 0;
for (p in this.data) l++;
return l;
}
}
})();
})();
Finally, you can seperate the instance and singleton properties and use a prototype for the instance's public methods. That results in the following syntax :
最后,您可以分离实例和单例属性,并为实例的公共方法使用原型。这导致以下语法:
var keyValueStore = (function() {
var count = 0; // Singleton private properties
var kvs = function() {
count++; // Instance private properties
this.data = {}; // Instance public properties
};
kvs.prototype = { // Instance public properties
'get' : function(key) { return this.data[key]; },
'set' : function(key, value) { this.data[key] = value; },
'delete' : function(key) { delete this.data[key]; },
'getLength' : function() {
var l = 0;
for (p in this.data) l++;
return l;
}
};
return { // Singleton public properties
'create' : function() { return new kvs(); },
'count' : function() { return count; }
};
})();
With this syntax, you can have :
使用此语法,您可以:
- multiple instances of an object
- private variables
- class variables
- 一个对象的多个实例
- 私有变量
- 类变量
You use it like this :
你像这样使用它:
kvs = keyValueStore.create();
kvs.set('Tom', "Baker");
kvs.set('Daisy', "Hostess");
var profession_of_daisy = kvs.get('Daisy');
kvs.delete('Daisy');
console.log(keyValueStore.count());
回答by Shanimal
"necromancing" here, but I think every great question needs simple answers:
“死灵”在这里,但我认为每个好问题都需要简单的答案:
Yesand Yes*
是和是*
By attaching the properties to the function you clean up the scope, improve readability and add logical cohesion. An added benefit is that you document the relationship between the function and the variables. I think that's a superior design, much better than adding variables on the scope
通过将属性附加到函数,您可以清理范围、提高可读性并添加逻辑内聚力。另一个好处是您可以记录函数和变量之间的关系。我认为这是一个卓越的设计,比在作用域上添加变量要好得多
Created some fun examples here and here. HEREAND HERE
* I think it's worth noting that you probably won't see this very often. most developers probably don't realize it's possible. Some people are crazy about every drop of performance... "JavaScript engines optimize based on the 'shape' of an object'..."blah blah blah... ut I think you can follow the rule you have for Objects and you'll do fine.
*我认为值得注意的是,您可能不会经常看到这种情况。大多数开发人员可能没有意识到这是可能的。有些人对每一滴性能都感到疯狂…… “JavaScript 引擎根据对象的‘形状’进行优化……”等等等等……但我认为你可以遵循你对对象的规则,然后你会好的。
回答by Domi
Attaching properties to functions is a beautiful (arguably sluggish/hack-ish) way of overloading the ()
operator, which in turn is usually used to implement functors: Object types that have one really important job, and all its other functionality (if there is any) is just a bunch of helpers. You could also interpret these functors as, basically, a "stateful" function where the state is public (most inline functions for example, have private state, that is state from the local scope).
将属性附加到函数是一种漂亮的(可以说是缓慢的/hack-ish)重载()
运算符的方式,而运算符又通常用于实现函子:具有一项非常重要的工作及其所有其他功能的对象类型(如果有的话) ) 只是一堆帮手。您还可以将这些函子解释为,基本上,状态是公共的“有状态”函数(例如,大多数内联函数具有私有状态,即来自本地范围的状态)。
This JSFiddledemonstrates how we can use a function with custom properties for a translator
function with additional utilities:
这个 JSFiddle演示了我们如何使用translator
带有附加实用程序的函数的自定义属性的函数:
/**
* Creates a new translator function with some utility methods attached to it.
*/
var createTranslator = function(dict) {
var translator = function(word) {
return dict[word];
};
translator.isWordDefined = function(word) {
return dict.hasOwnProperty(word);
};
// Add more utilities to translator here...
return translator;
};
// create dictionary
var en2deDictionary = {
'banana': 'Banane',
'apple': 'Apfel'
};
// simple use case:
var translator = createTranslator(en2deDictionary);
var pre = $('<pre>');
$("body").append(pre);
pre.append(translator('banana') + '\n');
pre.append(translator('apple') + '\n');
pre.append(translator.isWordDefined('w00t') + '\n');
As you can see, this is perfect for a translator whose sole purpose is to translate. Of course there are many more examples of theses types of objects, but they are by far not as common as types with diversified functionality, such as the classic User
, Animal
Car
etc. types. To those sort of types, you only want to add custom properties in very few cases. Usually, you want to define those as more complete classes, and have their public properties reachable through this
and it's prototype
.
如您所见,这对于以翻译为唯一目的的翻译人员来说是完美的。当然也有论文的对象类型的例子还有许多,但他们远远不是像普通类型的多样化功能,如经典的User
,Animal
Car
等类型。对于这些类型,您只想在极少数情况下添加自定义属性。通常情况下,要定义那些较为完善课程,并有自己的公共属性到达通过this
和它的prototype
。
回答by user456176
I realize I'm years late to this, but thought I'd add this example--requirejs sets a property called "amd" on the define() function, which is quite handy as the UMD pattern uses it to detect that the define() function that's in scope is in fact an AMD define() function.
我意识到我已经晚了几年,但我想我会添加这个例子——requirejs 在define() 函数上设置一个名为“amd”的属性,这非常方便,因为 UMD 模式使用它来检测定义() 作用域内的函数实际上是一个 AMD define() 函数。
RequireJS source: http://requirejs.org/docs/release/2.1.9/comments/require.js
RequireJS 源码:http://requirejs.org/docs/release/2.1.9/comments/require.js
UMD pattern showing this usage: https://github.com/umdjs/umd/blob/master/amdWeb.js
显示此用法的 UMD 模式:https: //github.com/umdjs/umd/blob/master/amdWeb.js
回答by Nitij
If you just want to add custom properties to a function then you only need to add those properties to Function.prototype. For example:
如果您只想向函数添加自定义属性,那么您只需要将这些属性添加到 Function.prototype 中。例如:
Function.prototype.SomeNewProperty = function () {//Do something awesome here...}
回答by AdamW
It's perfectly acceptable to add properties or methods to a function object. It's done quite often. The jQuery/$ object is an example of this. It's a function with quite a few methods attached.
向函数对象添加属性或方法是完全可以接受的。它经常这样做。jQuery/$ 对象就是一个例子。这是一个附加了很多方法的函数。
When properties are added to a constructor they are called 'static' properties and can be invoked without an an instance of the class. e.g. Object.create.
当属性被添加到构造函数时,它们被称为“静态”属性,可以在没有类的实例的情况下调用。例如 Object.create。
I don't have enough rep to write a comment so I will say here: It generally considered bad practice to extend the prototypes of built in objects, especially if your code has to play with other people's code. It can have unpredictable consequences that are hard to to track.
我没有足够的代表来写评论,所以我会在这里说:扩展内置对象的原型通常被认为是不好的做法,特别是如果您的代码必须与其他人的代码一起玩。它可能会产生难以追踪的不可预测的后果。
回答by loretoparisi
I agree that this is a difficult question that could have multiple answers, so I prefer to make an different example:
我同意这是一个可能有多个答案的难题,所以我更愿意举一个不同的例子:
Let's suppose to have an JavaScript Array
, populated by a generator:
假设有一个Array
由生成器填充的 JavaScript :
var arr = [...new Array(10).keys()];
that is
那是
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
Now we want to map this to a new array - same length, applying some function, so we could use the native map
function property:
现在我们想把它映射到一个新的数组 - 相同的长度,应用一些函数,所以我们可以使用原生map
函数属性:
arr = arr.map((value,index) => ++value)
We have just done a value=value+1
and return, so now the array will look like
我们刚刚做了一个value=value+1
并返回,所以现在数组看起来像
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Ok, now supposed to have a JavaScript Object
like
好的,现在应该有一个Object
像
var obj=new Object()
that was defined like the previous array (for some crazy reason):
它的定义与之前的数组一样(出于某种疯狂的原因):
arr.forEach((value,index) => obj[value]=value)
i.e.
IE
{0: 0, 1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, 7: 7, 8: 8, 9: 9}
At this point we cannot apply the same map
method since it's not defined for an Object
so we have to define it as a new prototype
of an Object
:
在这一点上,我们不能采用同样的map
,因为它不是一个定义的方法Object
,所以我们必须把它定义为一个新prototype
的Object
:
Object.defineProperty(Object.prototype, 'mapObject', {
value: function(f, ctx) {
ctx = ctx || this;
var self = this, result = {};
Object.keys(self).forEach(function(k) {
result[k] = f.call(ctx, self[k], k, self);
});
return result;
}
});
At this point we could do as for the array before:
此时我们可以像之前的数组一样:
obj=obj.mapObject((value,key) => ++value )
so that we have:
所以我们有:
{0: 1, 1: 2, 2: 3, 3: 4, 4: 5, 5: 6, 6: 7, 7: 8, 8: 9, 9: 10}
You can see that we have updated the values only:
您可以看到我们仅更新了值:
[...Object.keys(obj)]
["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"]
and we can turn back then into the output array:
然后我们可以返回到输出数组:
[...Object.keys(obj).map(k=>obj[k])]
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Here it is at work:
这是在工作:
// Array.map
var arr = [...new Array(10).keys()];
console.log("array", arr)
arr = arr.map((value, index) => ++value)
console.log("mapped array", arr)
// new property
Object.defineProperty(Object.prototype, 'mapObject', {
value: function(f, ctx) {
ctx = ctx || this;
var self = this,
result = {};
Object.keys(self).forEach(function(k) {
result[k] = f.call(ctx, self[k], k, self);
});
return result;
}
});
// Object.mapObject
var obj = new Object()
arr = [...new Array(10).keys()];
arr.forEach((value, index) => obj[value] = value)
console.log("object", obj)
obj = obj.mapObject((value, key) => ++value)
console.log("mapped object", obj)
console.log("object keys", [...Object.keys(obj)])
console.log("object values", [...Object.keys(obj).map(k => obj[k])])
回答by brat
Possible addition to John Slegers great answer
可能除了约翰·斯莱格斯的好答案
Isnt it possible that after John Slegers:
难道在约翰·斯莱格斯之后:
Way 2 : adding properties after defining the function
方式二:定义函数后添加属性
Adding a Way 2.5
添加方式 2.5
function doSomething() {
doSomething.prop = "Bundy";
doSomething.doSomethingElse = function() {
alert("Why Hello There! ;)");
};
let num = 3;
while(num > 0) {
alert(num);
num--;
}
}
sayHi();
sayHi.doSomethingElse();
alert(doSomething.prop);
var ref = doSomething;
ref();
ref.doSomethingElse();
alert(ref.prop);
Putting in both a "variable" property and a function property for completeness sake, straight in the function declaration. Thus avoiding it to be "disconnected". Left the inner default workings of the function (a simple loop) to show that it still works. No?
为了完整起见,直接在函数声明中放入“变量”属性和函数属性。从而避免它被“断开”。保留函数的内部默认工作方式(一个简单的循环)以表明它仍然有效。不?
回答by Zibri
test = (function() {
var a = function() {
console.log("test is ok");
};
a.prop = "property is ok";
a.method = function(x, y) {
return x + y;
}
return a
})()
test();
console.log(test.prop);
console.log(test.method(3, 4));
Alternatively you have to use getters and setters
或者,您必须使用 getter 和 setter
var person = {
firstName: 'Jimmy',
lastName: 'Smith',
get fullName() {
return this.firstName + ' ' + this.lastName;
},
set fullName(name) {
var words = name.toString().split(' ');
this.firstName = words[0] || '';
this.lastName = words[1] || '';
}
}
console.log(person.firstName);
console.log(person.lastName);
console.log(person.fullName);
person.fullName = "Tom Jones";
console.log(person.fullName);