Object.create() VS functions

# Michaël Rouges (12 years ago)

Bonjour à tous,

`Knowing that every function is an object, I am surprised that the Object.create() method doesn't really allow cloning function.

So I made ​​an implementation as follows:

`Object.create = (function () { 'use strict';

var slice,
    curry,
    getOwnPropertyNames,
    getOwnPropertyDescriptor,
    defineProperty,
    onProperty,
    onDescriptor,
    create;

slice = (function () {
    var method;

    method = [].slice;

    return method.call.bind(method);
}());

curry = function curry(fn) {
    var args;

    args = slice(arguments, 1);

    return function() {
        return fn.apply(
            this,
            args.concat(
                slice(arguments)
            )
        );
    };
};

getOwnPropertyNames = curry(Object.getOwnPropertyNames);

getOwnPropertyDescriptor = curry(Object.getOwnPropertyDescriptor);

defineProperty = curry(Object.defineProperty);

onProperty = function onProperty(prototype, property) {
    var descriptor;

    descriptor = getOwnPropertyDescriptor(this, property);

    if (descriptor === undefined || descriptor.writable ||

descriptor.configurable) { defineProperty(this, property, getOwnPropertyDescriptor(prototype, property)); } };

onDescriptor = function onDescriptor(propertyDescriptors, property) {
    defineProperty(this, property, propertyDescriptors[property]);
};

create = function create(prototype, propertyDescriptors) {
    var returnValue, onProtoProperty, onPropertyDescriptor;

    returnValue = prototype instanceof Function
    ? curry(prototype)
    : {};

    getOwnPropertyNames(prototype)
    .forEach(onProperty.bind(returnValue, prototype));

    if (typeof propertyDescriptors === 'object') {
        getOwnPropertyNames(propertyDescriptors)
        .forEach(onDescriptor.bind(returnValue, propertyDescriptors));
    }

    return returnValue;
};

return create;

}());`

Is there a reason not to do that, please?

Thanks in advance.

Michaël Rouges - Lcfvs - @Lcfvs

# Brandon Benvie (12 years ago)

On 10/26/2013 7:44 AM, Michaël Rouges wrote:

Knowing that every function is an object, I am surprised that the Object.create() method doesn't really allow cloning function.

Object.create creates Objects. You run into the same limitation when trying to create Arrays with Object.create (doesn't work correctly). You're looking for Function.create [1], which doesn't yet exist (although you can get pretty close using Proxies for functions).

[1] A sample implementation of Function.create can be found on strawman:name_property_of_functions

# David Bruant (12 years ago)

Le 26/10/2013 15:44, Michaël Rouges a écrit :

Bonjour à tous,

Bonjour,

`Knowing that every function is an object, I am surprised that the Object.create() method doesn't really allow cloning function.

I don't follow the logic of this sentence. In any case, the purpose of Object.create is to create a normal object, that is an object as commonly understood when it comes to its own properties (no magic property like array's "length"), without private state (like Date objects) and that is not callable. Also, Object.create does not create a clone, but a new object.

<implementation>

If you don't care about |this|, f2 = f.bind(undefined) can be considered as a way to clone a function.

function f2(){ return f.apply(this, arguments); } works too.

f2 = new Proxy(f, {}) is a form of function cloning as well.

Very much like object cloning, function cloning does not have one unique definition.

Is there a reason not to do that, please?

I would ask the opposite question: is there a reason to do that? Usually features are added because there is a driving use case which you haven't provided.

Also, usually, changing the semantics of an existing built-in isn't a good idea given that it may break existing code relying on it.

Last, if you can implement it yourself, why do you need it to be part of the language? There are hundreds of convenience functions that could be added. Why this one more than others?

Thanks,

# Nathan Wall (12 years ago)

Before getting into the exact situation with Object.create and functions, the first thing to understand is that Object.create(proto) creates an object with prototype of proto.  As others have said, this is different from cloning.

Here's a simple example which should show the differences between the built-in Object.create and your version which creates a clone.

var A = { foo: 1 },         B = Object.create(A);

A.foo = 7;     console.log(B.foo); // => 7

With your version of Object.create, the last line would log 1 instead of 7.  With built-in Object.create it's 7 because A is the prototype of B, so on property access all own properties of B are checked first and if a match isn't found then the properties of A are checked.

To continue the above example:

B.foo = 8;     console.log(B.foo); // => 8

delete B.foo;     console.log(B.foo); // => 7

Make sense?

Nathan

# Michaël Rouges (12 years ago)

Thank you for your answers.

Sorry for my misnomer, I meant "to copy a function", not "to clone a function".

In fact, it's been a while I do the technical research around the JavaScript , and this research has led me to realize that there is no feature to simply copy a function (or class) , including the properties thereof.

Regarding your exremièrement, there is a major difference between fn.bind() and new Proxy(fn), fn.bind() doesn't copy the properties of the initial function.

Then, new Proxy(fn) doesn't allow to add properties to the returned function as my Object.create().

@Nathan : Thanks, a little too excited in my mind, I have made ​​a mistake, I will correct it. ;)

Michaël Rouges - Lcfvs - @Lcfvs