溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

javascript的Object.assign()怎么用

發(fā)布時間:2022-03-03 17:20:49 來源:億速云 閱讀:141 作者:iii 欄目:開發(fā)技術

這篇“javascript的Object.assign()怎么用”文章的知識點大部分人都不太理解,所以小編給大家總結了以下內容,內容詳細,步驟清晰,具有一定的借鑒價值,希望大家閱讀完這篇文章能有所收獲,下面我們一起來看看這篇“javascript的Object.assign()怎么用”文章吧。

如下:

const defaultOpt = {
    key1: xxx,
    key2: {
        dd: ee
    },
    .....
};
// deepCopy為某個實現(xiàn)深拷貝的方法
const opt1 = deepCopy(defaultOpt);
opt1.....
const opt2 = deepCopy(defaultOpt);
opt2.....

深拷貝和淺拷貝

這里也涉及到一個深拷貝和淺拷貝的概念。javascript中存儲對象都是存地址的,所以淺拷貝是都指向同一塊內存區(qū)塊,而深拷貝則是另外開辟了一塊區(qū)域。

下面實例也可以看出這一點:

// 淺拷貝
const a = {t: 1, p: 'gg'};
const b = a;
b.t = 3;
console.log(a); // {t: 3, p: 'gg'}
console.log(b); // {t: 3, p: 'gg'}
//深拷貝
const c = {t: 1, p: 'gg'};
const d = deepCopy(c);
d.t = 3;
console.log(c); // {t: 1, p: 'gg'}
console.log(d); // {t: 3, p: 'gg'}

可以明顯看出,淺拷貝在改變其中一個值時,會導致其他也一起改變,而深拷貝不會。

Object.assign()

我需要的是深拷貝的方法,然后發(fā)現(xiàn)原來es6 中有Object.assign() 這個方法,感覺可以拿來用了。

貼一下兩個官方例子:

// Cloning an object
var obj = { a: 1 };
var copy = Object.assign({}, obj);
console.log(copy); // { a: 1 }
// Merging objects
var o1 = { a: 1 };
var o2 = { b: 2 };
var o3 = { c: 3 };
var obj = Object.assign(o1, o2, o3);
console.log(obj); // { a: 1, b: 2, c: 3 }
console.log(o1);  // { a: 1, b: 2, c: 3 }, target object itself is changed.

是不是很完美,又可以clone又可以merge。在我這種情況下,我覺得我的代碼量又可以減少了,比如:

const defaultOpt = {
    title: 'hello', 
    name: 'oo', 
    type: 'line'
};
// 原來可能需要這樣
const opt1 = deepCopy(a);
opt1.title = 'opt1';
opt1.type = 'bar';
opt1.extra = 'extra'; // 額外增加配置
// 現(xiàn)在只要這樣
const opt2 = Object.assign({}, a, {
    title: 'opt2', 
    type: 'bar', 
    extra: 'extra'
});

不過,很快,問題出現(xiàn)了,那就是

merge和我想象的不一樣

且看例子:

const defaultOpt = {
    title: {
        text: 'hello world',
        subtext: 'It\'s my world.'
    }
};
const opt = Object.assign({}, defaultOpt, {
    title: {
        subtext: 'Yes, your world.'
    }
});
console.log(opt);
// 預期結果
{
    title: {
        text: 'hello world',
        subtext: 'Yes, your world.'
    }
}
// 實際結果
{
    title: {
        subtext: 'Yes, your world.'
    }
}

原本想的是它只會覆蓋subtext ,然而其實它直接覆蓋了整個title ,這個讓我比較郁悶,相當于它只merge根屬性,下面的就不做處理了。

代碼只能重構成相對麻煩一點的:

const defaultOpt = {
    title: {
        text: 'hello world',
        subtext: 'It\'s my world.'
    }
};
const opt = Object.assign({}, defaultOpt);
opt.title.subtext = 'Yes, your world.';
console.log(opt);
// 結果正常
{
    title: {
        text: 'hello world',
        subtext: 'Yes, your world.'
    }
}

這樣用雖然麻煩一點,但是也還好,可以用了。不過。。。很快,又出現(xiàn)問題了,如下:

const defaultOpt = {
    title: {
        text: 'hello world',
        subtext: 'It\'s my world.'
    } 
};
const opt1 = Object.assign({}, defaultOpt);
const opt2 = Object.assign({}, defaultOpt);
opt2.title.subtext = 'Yes, your world.';
console.log('opt1:');
console.log(opt1);
console.log('opt2:');
console.log(opt2);
// 結果
opt1:
{
    title: {
        text: 'hello world',
        subtext: 'Yes, your world.'
    }
}
opt2:
{
    title: {
        text: 'hello world',
        subtext: 'Yes, your world.'
    }
}

上面結果發(fā)現(xiàn)兩個配置變得一模一樣,而其實我們并沒有去更改opt1 的subtext ,只是改了opt2 的。

這說明一點:在title 這一層只是簡單的淺拷貝 ,而沒有繼續(xù)深入的深拷貝。

這里不經(jīng)讓我懷疑這個接口到底是怎么實現(xiàn)的,它到底是不是和我所想的一樣。

翻了一下官方文檔,發(fā)現(xiàn)它寫得一個Polyfill ,代碼我加了點注釋如下:

if (!Object.assign) {
    // 定義assign方法
  Object.defineProperty(Object, 'assign', {
    enumerable: false,
    configurable: true,
    writable: true,
    value: function(target) { // assign方法的第一個參數(shù)
      'use strict';
      // 第一個參數(shù)為空,則拋錯
      if (target === undefined || target === null) {
        throw new TypeError('Cannot convert first argument to object');
      }
      var to = Object(target);
      // 遍歷剩余所有參數(shù)
      for (var i = 1; i < arguments.length; i++) {
        var nextSource = arguments[i];
        // 參數(shù)為空,則跳過,繼續(xù)下一個
        if (nextSource === undefined || nextSource === null) {
          continue;
        }
        nextSource = Object(nextSource);
        // 獲取改參數(shù)的所有key值,并遍歷
        var keysArray = Object.keys(nextSource);
        for (var nextIndex = 0, len = keysArray.length; nextIndex < len; nextIndex++) {
          var nextKey = keysArray[nextIndex];
          var desc = Object.getOwnPropertyDescriptor(nextSource, nextKey);
          // 如果不為空且可枚舉,則直接淺拷貝賦值
          if (desc !== undefined && desc.enumerable) {
            to[nextKey] = nextSource[nextKey];
          }
        }
      }
      return to;
    }
  });
}

上面的代碼可以直接說明它只對頂層屬性做了賦值,完全沒有繼續(xù)做遞歸之類的把所有下一層的屬性做深拷貝。

小結一下

Object.assign() 只是一級屬性復制,比淺拷貝多深拷貝了一層而已。用的時候,還是要注意這個問題的。

附:發(fā)現(xiàn)一個可以簡單實現(xiàn)深拷貝的方法,當然,有一定限制,如下:

const obj1 = JSON.parse(JSON.stringify(obj));

思路就是將一個對象轉成json字符串,然后又將字符串轉回對象。 

細說一下Object.assign()

Object.assign()

  • Object.assign() 第一個參數(shù)是目標對象,后面的都是源對象。 Object.assign (target, source1,source2, source3, &hellip;);

  • 如果源對像與目標對象有相同的屬性名,或源對象中有相同的屬性名,后面的會覆蓋前邊的值 。

  • 如果參數(shù)傳入的不是Object,會轉成Object

  • null和undefined 不能作為參數(shù)傳入,因為null和undefined 不能轉成Object

  • 如果發(fā)生的值是一個對象,Object.assign的處理方法是直接替換,而不是添加。 如下面的 a 和 b

  • 可以為類添加方法

const obj1  = {name:'小明', age:'18',education:'undergraduate'}
    const obj2 = {height:'180cm',hobby:'painting'}
    let  obj = Object.assign({},obj1, obj2)
    console.log('合并后的類:');
    console.log(JSON.stringify(obj));
    Object.assign(obj, obj, {height:'170cm'});
    console.log('修改過height后的類:');
    console.log(JSON.stringify(obj));
    Object.assign(obj, {arr:{index:1, name:'類'}}, {name:'加了一個類進去'})
    console.log(JSON.stringify(obj));
    console.log("加一個類進去后:"+obj.arr.index);
    // a. 這種修改方式,只會修改index 的值
    Object.assign(obj, Object.assign(obj.arr, {index:2}))
    console.log(JSON.stringify(obj));
    console.log("修改類index后:"+obj.arr.index);
    // b. 這種修改方式,arr只剩下index屬性
    // Object.assign(obj, {arr:{index:2}}, {name:'修改類的index為:2'})
    // console.log(JSON.stringify(obj));
    // console.log("修改類index后:"+obj.arr.index);
    // Object.assign()做的是淺拷貝, 如果一個屬性是新合并進來的對象,改變源對象的值,會影響合并后的值 。
    let newObj  = {type:{aa:'蔬菜'}};
    Object.assign(obj, newObj);
    console.log("合并一個含屬性type的類后:"+JSON.stringify(obj));
    // c. 這種不會影響obj中的type.aa
    // Object.assign(newObj, {type:{aa:'水果'}});
    // d. 這種會影響obj中的type.aa
    newObj.type.aa = '水果';
    console.log("修改newObj中的type.aa后:"+JSON.stringify(newObj));
    console.log("修改newObj中的type.aa后:"+JSON.stringify(obj));
    // e. 用Object.assign合并一個數(shù)組的時候,會把數(shù)組當成一個屬性名為index的類
    const arr1  = [1, 2, 3, 4, 5] ;  // 在Object的眼里是這樣的: arr1={0:1, 1:2, 2:3,3:4, 4:5}
    const arr2 =  [8, 9, 10];        // 在Object的眼里是這樣的: arr2={0:8, 1:9, 2:10}
    console.log("合并后的數(shù)組為:"+Object.assign(arr1, arr2)); // 得到的結果是:8, 9, 10, 4, 5
    // f. Object.assign() 為類添加方法
    Object.assign(UserInfo.prototype, {
      getUserName (){
        return this.name;
      },
      getUserGender (){
        return this.gender ;
      }
    })
    let user  = new UserInfo("笑笑", '女');
    console.log("userinfo中的信息為: "+ user.getUserName() +", "+user.getUserGender()); // 輸出的結果為:笑笑,女

輸出的結果:

ObjectAssignDemo.js:13 合并后的類:
ObjectAssignDemo.js:14 {"name":"小明","age":"18","education":"undergraduate","height":"180cm","hobby":"painting"}
ObjectAssignDemo.js:16 修改過height后的類:
ObjectAssignDemo.js:17 {"name":"小明","age":"18","education":"undergraduate","height":"170cm","hobby":"painting"}
ObjectAssignDemo.js:19 {"name":"加了一個類進去","age":"18","education":"undergraduate","height":"170cm","hobby":"painting","arr":{"index":1,"name":"類"}}
ObjectAssignDemo.js:20 加一個類進去后:1
ObjectAssignDemo.js:24 {"name":"類","age":"18","education":"undergraduate","height":"170cm","hobby":"painting","arr":{"index":2,"name":"類"},"index":2}
ObjectAssignDemo.js:25 修改類index后:2
ObjectAssignDemo.js:35 合并一個含屬性type的類后:{"name":"類","age":"18","education":"undergraduate","height":"170cm","hobby":"painting","arr":{"index":2,"name":"類"},"index":2,"type":{"aa":"蔬菜"}}
ObjectAssignDemo.js:40 修改newObj中的type.aa后:{"type":{"aa":"水果"}}
ObjectAssignDemo.js:41 修改newObj中的type.aa后:{"name":"類","age":"18","education":"undergraduate","height":"170cm","hobby":"painting","arr":{"index":2,"name":"類"},"index":2,"type":{"aa":"水果"}}
ObjectAssignDemo.js:46 合并后的數(shù)組為:8,9,10,4,5
ObjectAssignDemo.js:58 userinfo中的信息為: 笑笑, 女

以上就是關于“javascript的Object.assign()怎么用”這篇文章的內容,相信大家都有了一定的了解,希望小編分享的內容對大家有幫助,若想了解更多相關的知識內容,請關注億速云行業(yè)資訊頻道。

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權內容。

AI