简体   繁体   English

向函数添加自定义属性

[英]Adding custom properties to a function

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 instances, 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.当使用 Firebug 的 DOM 浏览器检查时,该属性按预期定义。 However, as I don't consider myself a JavaScript expert, I have the following questions:但是,由于我不认为自己是 JavaScript 专家,所以我有以下问题:

  1. 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 浏览器中可以按预期运行很多东西,而且无论如何都不是标准。
  2. Is this kind of altering objects by adding new properties to them a good practice?这种通过向对象添加新属性来更改对象是一种好习惯吗?

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 :方式2:定义函数后添加属性:

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:创建一个可扩展函数对象并使用它将扩展函数附加到函数:

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.万一未来的浏览器曾经向函数原型添加原生“扩展”函数,这可能会破坏你的代码。


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());

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函数将可以访问其他属性通过this关键字的something )。

If you are using a function as a constructor it typically makes sense to add methods to 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 already exists and if so assigns it a new value.您显示的特定代码没有添加属性,它测试someProperty属性是否已经存在,如果存在,则为其分配一个新值。

You might benefit from reading some articles such as these at MDN:您可能会从阅读 MDN 上的一些文章中受益:

"necromancing" here, but I think every great question needs simple answers: “死灵法”在这里,但我认为每个伟大的问题都需要简单的答案:

Yes and 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.在这里和这里创建了一些有趣的例子。 HERE AND 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引擎优化基于对象的'形状'......”等等等等......但我认为你可以遵循你对对象的规则和你会好的。

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.将属性附加到函数是重载()运算符的一种漂亮(可以说是缓慢/hack-ish)方式,而后者通常用于实现函子:具有一项非常重要的工作的对象类型,以及它的所有其他功能(如果有是任何)只是一堆帮手。 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).基本上,您也可以将这些函子解释为状态为公共的“有状态”函数(例如,大多数内联函数具有私有状态,即来自本地范围的状态)。

This JSFiddle demonstrates 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.当然,这些对象类型的例子还有很多,但它们远没有像经典的UserAnimal Car等具有多种功能的类型那样普遍。 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 .通常,您希望将它们定义为更完整的类,并通过this和它的prototype来访问它们的公共属性。

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 模式使用它来检测define () 范围内的函数实际上是 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/templates/amdWeb.js显示此用法的 UMD 模式: https ://github.com/umdjs/umd/blob/master/templates/amdWeb.js

If you just want to add custom properties to a function then you only need to add those properties to Function.prototype.如果您只想为函数添加自定义属性,则只需将这些属性添加到 Function.prototype。 For example:例如:

Function.prototype.SomeNewProperty = function () {//Do something awesome here...}

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. jQuery/$ 对象就是一个例子。 It's a function with quite a few methods attached.这是一个附加了很多方法的函数。

When properties are added to a constructor they are called 'static' properties and can be invoked without an an instance of the class.当属性被添加到构造函数时,它们被称为“静态”属性,并且可以在没有类实例的情况下调用。 eg 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.它可能会产生难以追踪的不可预测的后果。

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:假设有一个由生成器填充的 JavaScript Array

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好的,现在应该有一个 JavaScript Object

var obj=new Object()

that was defined like the previous array (for some crazy reason):就像前面的数组一样定义(出于某种疯狂的原因):

arr.forEach((value,index) => obj[value]=value)

ie 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定义,所以我们必须将它定义为Object的新prototype

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])])

Possible addition to John Slegers great answer约翰斯莱杰斯的可能补充很好的答案

Isnt it possible that after John Slegers:有没有可能在约翰·斯莱杰斯之后:

Way 2 : adding properties after defining the function方式2:定义函数后添加属性

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?不?

 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);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM