// for IE11
/*?
Object.assign() 靜態(tài)方法將一個或者多個源對象中所有可枚舉的自有屬性復(fù)制到目標(biāo)對象,并返回修改后的目標(biāo)對象。
const target = { a: 1, b: 2 };
const source = { b: 4, c: 5 };
const returnedTarget = Object.assign(target, source);
console.log(target);
// Expected output: Object { a: 1, b: 4, c: 5 }
console.log(returnedTarget === target);
// Expected output: true
target
需要應(yīng)用源對象屬性的目標(biāo)對象,修改后將作為返回值。
sources
一個或多個包含要應(yīng)用的屬性的源對象。
*/
if (!Object.assign) {
? ? Object.assign = function (target, source) {
? ? ? ? /* 調(diào)用引擎方法,cc-js cc.js =js 這部分在flatform部分詳細(xì)講解 */
? ? ? ? return cc.js.mixin(target, source);
? ? }
}
// for Baidu browser
// Implementation reference to:?
// http://2ality.com/2016/02/object-getownpropertydescriptors.html
// http://docs.w3cub.com/javascript/global_objects/reflect/ownkeys/
/*?
?在ES2017的版本中,Object對象新增了一個方法——Object.getOwnPropertyDescriptors。這個方法主要的作用是返回屬性的描述對象(descriptor)。
?const obj = {
? ?prop1 : 100,
? ?prop2 : "字符串屬性",
? ?get bar(){return "bar返回字符串"}
}
Object.getOwnPropertyDescriptors(obj);
{prop1: {…}, prop2: {…}, bar: {…}}bar: {get: ?, set: undefined, enumerable: true,?
? ? configurable: true}configurable: trueenumerable:?
? ? trueget: ? bar()arguments: (...)caller: (...)length: 0
? ? name: "get bar"__proto__: ? ()apply: ? apply()arguments: (...)
? ? bind: ? bind()call: ? call()caller: (...)constructor: ? Function()
? ? length: 0name: ""toString: ? toString()Symbol(Symbol.ha…………
在瀏覽器里運行代碼,會得到上面的結(jié)果。數(shù)據(jù)很多,但能看出都是關(guān)于各個屬性的特性的描述文字。
? ? ?Object.getOwnPropertyDescriptors 方法返回一個對象,所有原來的對象的屬性名都是該對象的屬性名,對應(yīng)的屬性值就是該屬性的描述對象。
? ? ? 現(xiàn)在我們知道了,我們用Object.getOwnPropertyDescriptors能夠查看對象屬性的特性,
? ? ? 讓我們開發(fā)的時候?qū)@個對象心里有底。但是這個接口還有什么實際作用呢?
? ? ? 作用:克隆對象。
? ? ? 之前我們談過,用Object.assign()能克隆對象,其原理是把一個現(xiàn)有的對象和一個空對象合并之后,
? ? ? 空對象就有了現(xiàn)有對象的屬性。這樣空對象好像就變成了源對象的克隆體一樣。
? ? ? 這種方法在通常情況下是沒問題的,但是有一個前提是Object.assign()接口無法正確拷貝set屬性和get屬性的對象。
? ? ? 因為assign做合并的時候,只能拷貝一個屬性值,不會把它背后的賦值方法或者取值方法一同拷貝過來。所以在這種情況下,
? ? ? 我們就可以用Object.getOwnPropertyDescriptors方法,配合Object.defineProperties方法,實現(xiàn)克隆對象的功能。
? ? ? ? 這種方法的原理是將源對象的所有屬性描述對象,提取出來,根據(jù)這個描述對象,重新定義一個空對象的屬性。代碼如下:?
? ? ? ? const source = {
? ? ? ? set foo(value) {
? ? ? ? ? ? console.log(value);
? ? ? ? }
? ? ? ? };
? ? ? ? const target2 = {};
? ? ? ? Object.defineProperties(target2, Object.getOwnPropertyDescriptors(source));
? ? ? ? Object.getOwnPropertyDescriptor(target2, 'foo')
? ? ? ? // { get: undefined,
? ? ? ? //? ?set: [Function: set foo],
? ? ? ? //? ?enumerable: true,
? ? ? ? //? ?configurable: true }
? ? ? ? ? ? ?我們還有另一種方法,讓getOwnPropertyDescriptors方法配合Object.create方法,來克隆對象
? ? ? ? ? ? ? ? var source = {
? ? ? ? ? ? ? ? ? ? prop1 : "prop1",
? ? ? ? ? ? ? ? ? ? prop2 : 100;
? ? ? ? ? ? ? ? ? ? }
? ? ? ? // source 是源對象,我們獲取source的原型對象和source的屬性描述對象,根據(jù)二者生成的新對象就是source的克隆
? ? ? ? var clone = Object.create(Object.getPrototypeOf(source),Object.getOwnPropertyDescriptors(source));
*/
if (!Object.getOwnPropertyDescriptors) {
? ? Object.getOwnPropertyDescriptors = function (obj) {
? ? ? ? /* 聲明一個對象,用于存儲屬性描述對象 */
? ? ? ? let descriptors = {};
? ? ? ? /* getOwnPropertyNames-
? ? ? ? 該方法返回對象自身屬性的名稱。對象自身的屬性是直接定義的屬性 在該對象上,并且不是從該對象的原型繼承的。對象的屬性包括字段(對象)和函數(shù)。 */
? ? ? ? let ownKeys = Object.getOwnPropertyNames(obj);
? ? ? ? /* getOwnPropertySymbols
? ? ? ? 該方法返回直接在對象 o 上找到的所有符號屬性的數(shù)組。 */
? ? ? ? if (Object.getOwnPropertySymbols) { // for IE 11
? ? ? ? ? ? ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(obj));
? ? ? ? }
? ? ? ? for (let i = 0; i < ownKeys.length; ++i) {
? ? ? ? ? ? let key = ownKeys[i];
? ? ? ? ? ? /* 存儲屬性描述對象 */
? ? ? ? ? ? descriptors[key] = Object.getOwnPropertyDescriptor(obj, key);
? ? ? ? }
? ? ? ? return descriptors;
? ? }
}