Skip to content

Instantly share code, notes, and snippets.

@rwaldron
Last active September 9, 2021 07:03
Show Gist options
  • Save rwaldron/3350283 to your computer and use it in GitHub Desktop.
Save rwaldron/3350283 to your computer and use it in GitHub Desktop.
Object.assign = function( O, dictionary ) {
var target, src;
// Let target be ToObject(O).
target = Object( O );
// Let src be ToObject(dictionary).
src = Object( dictionary );
// For each own property of src, let key be the property key
// and desc be the property descriptor of the property.
Object.getOwnPropertyNames( src ).forEach(function( key ) {
target[ key ] = src[ key ];
});
return target;
};
// Basic tests...
//
var bagOfStuff, resultOfAssign, cycled, fixture, ref, arr, div, node;
bagOfStuff = {
get one() {
return 1;
},
num: 2,
// this will be paved over
// and no longer update this.num
set val( value ) {
this.num = value;
},
get val( value ) {
return this.num;
}
};
ref = { b: "baz" };
arr = [ ref, 1, 2 ];
resultOfAssign = Object.assign( bagOfStuff, {
val: 10,
get f() {
return "foo";
},
boundOp: function( x ) {
return this.val * x;
},
ref: ref,
arr: arr,
circular: resultOfAssign
});
console.log(
bagOfStuff == resultOfAssign,
"Object.assign returns the target object, (similar to Object.defineProperty"
);
console.log(
resultOfAssign.val === 10,
"Assigning a value to an existing accessor works correctly (assigning directly)"
);
console.log(
resultOfAssign.num === 10,
"Assigning a value to an existing accessor works correctly (update via accessor)"
);
cycled = JSON.parse( JSON.stringify(resultOfAssign) );
Object.keys(fixture = {
one: 1,
num: 10,
val: 10,
f: "foo"
}).forEach(function( key ) {
console.log(
cycled[ key ] === fixture[ key ],
"JSON cycled matches fixture", fixture[ key ]
);
});
// Changing this will cause the value of "num" to be updated as well
resultOfAssign.val = 4;
// The new value of
console.log(
resultOfAssign.num === 4,
"Direct assignment to accessor property"
);
console.log(
resultOfAssign.boundOp(2) === 8,
"Method bound to correct target object"
);
// add a new prop to the reference object
ref.a = "alpha";
console.log(
resultOfAssign.ref.a === "alpha",
"prop whose value is an object, updated by reference"
);
// change an element in the reference array
arr[0] = 0;
console.log(
resultOfAssign.arr[0] === 0,
"prop whose value is an array, updated by reference"
);
// Using empty objects
var a, b, c;
a = Object.assign({}, { f: "foo" });
console.log(
a.f === "foo",
"Create from an empty object ([[Prototype]] intact)"
);
b = Object.assign({ __proto__: null }, { f: "foo" });
console.log(
b.f === "foo",
"Create from an empty object ([[Prototype]] null)"
);
c = Object.assign( Object.create(null), { f: "foo" });
console.log(
c.f === "foo",
"Create from an empty object (Object.create(null))"
);
// Using constructed object
function Room( w, h ) {
this.w = w;
this.h = h;
this.exists = true;
}
Room.prototype = {
get squareFt() {
return this.w * this.h;
}
};
var room, copy;
room = new Room( 10, 10 );
copy = {
exists: false
};
Object.assign( copy, room );
console.log(
copy.w === 10 && copy.h === 10 && copy.exists === true,
"Own instance properties are assigned"
);
console.log(
copy.squareFt === undefined,
"proto accessors are not assigned"
);
// Reverse, give a new instance some properties
// This is REALLY stupid, but people do it.
function Zone() {}
Zone.prototype = {
get squareFt() {
return this.w * this.h;
}
};
var zone, dims;
zone = new Zone();
dims = {
w: 5,
h: 5,
// Whoooooops!
squareFt: 100000000
};
Object.assign( zone, dims );
console.log(
zone.w === 5 && zone.h === 5,
"Properties are assigned"
);
console.log(
zone.squareFt === 25,
"proto accessors are not clobbered"
);
var o, identity;
identity = function( x ) { return x; };
identity.foo = "expando";
o = Object.assign( {}, identity );
console.log(
o.foo === "expando",
"Function object expandos"
);
var api, src;
api = {
init: function() {
this.put = true;
}
};
src = {
put: false
};
api = Object.assign( api, src );
api.init();
console.log(
api.put === true,
"Received a property via Object.assign, assigned it a value"
);
console.log(
src.put === false,
"Sending object retained property value"
);
// DOM example...
function simulateClick( elem ) {
var evt;
evt = document.createEvent( "MouseEvents" );
evt.initMouseEvent(
"click", true, true,
window, 0, 0, 0, 0, 0,
false, false, false, false, 0, null
);
elem.dispatchEvent( evt );
}
if ( typeof document !== "undefined" ) {
div = document.createElement("div");
div.hidden = true;
div.innerHTML = "Assign an initial value";
document.body.appendChild( div );
// Update many properties of the target object;
// these are examples of DOM element properties
// that have specific accessor and/or data property
// behaviours
Object.assign( div, {
innerHTML: "<p>A new value is assigned!</p>",
id: "my-div",
hidden: false,
onclick: function(e) {
console.log( e.type === "click", "(DOM 0 onclick)" );
},
get foo() {
return "Foo return by accessor";
},
});
// Now let's get a reference to the node by different means...
node = document.getElementById("my-div");
// It should have a single P child
console.log(
node.children.length === 1,
"(node.children.length equals 1)"
);
// Its innerHTML should equal the new string we assigned
// previously
console.log(
node.innerHTML === "<p>A new value is assigned!</p>",
"(node.innerHTML equals the assigned string value)"
);
// DOM 0 event handler properties should behave as expected.
simulateClick( div );
}
true 'Object.put returns the target object, (similar to Object.defineProperty'
true 'Assigning a value to an existing accessor works correctly (assigning directly)'
true 'Assigning a value to an existing accessor works correctly (update via accessor)'
true 'JSON cycled matches fixture' 1
true 'JSON cycled matches fixture' 10
true 'JSON cycled matches fixture' 10
true 'JSON cycled matches fixture' 'foo'
true 'Direct assignment to accessor property'
true 'Method bound to correct target object'
true 'prop whose value is an object, updated by reference'
true 'prop whose value is an array, updated by reference'
true 'Create from an empty object ([[Prototype]] intact)'
true 'Create from an empty object ([[Prototype]] null)'
true 'Create from an empty object (Object.create(null))'
true 'Own instance properties are assigned'
true 'proto accessors are not assigned'
true 'Properties are assigned'
true 'proto accessors are not clobbered'
true 'Function object expandos'
true 'Received a property via Object.put, assigned it a value'
true 'Sending object retained property value'
true '(node.children.length equals 1)'
true '(node.innerHTML equals the assigned string value)'
true '(DOM 0 onclick)'
@ravindra-thorat
Copy link

It won't work for Object.assign(...[{key1: 1}, {key2: 2}, {key3: 3}, {key4: 4}])

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment