Last active
September 9, 2021 07:03
-
-
Save rwaldron/3350283 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 ); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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)' |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
It won't work for
Object.assign(...[{key1: 1}, {key2: 2}, {key3: 3}, {key4: 4}])