1. 程式人生 > >ES6對象的擴展

ES6對象的擴展

logs 實例化 構造 和數 進行 對象修改 set 有一個 初學者

ES6不僅為字符串、數值和數組帶來了擴展,也為對象帶來了很多新特性。這一節,我們來一起學習一下對象的擴展。

對象的傳統表示法

我們回顧一下,對象的傳統表示法:

1    let person = {
2         "name":"張三",
3         "say":function(){
4             alert("你好嗎?");
5         }
6     }

上面的案例很簡單,變量person就是一個對象,對象含有name屬性和一個say方法。表示法是用鍵值對的形式來表示,這就是傳統的表示法。

ES6中的簡潔寫法

ES6給我們帶來了更簡便的表示法,我們一起來對比一下:

 1  var name = "Zhangsan";
 2     var age = 12;
 3 
 4     //傳統的屬性寫法
 5     var person = {
 6         "name":name,
 7         "age":age
 8     };
 9     console.log(person);
10     //結果:{name: "Zhangsan", age: 12}
11 
12 
13     //ES6的屬性寫法
14     var person = {name,age};
15     console.log(person);
16     //結果:{name: "Zhangsan", age: 12}

咱們來講解一下上面這個案例,首先定義兩個變量name和age,分別用傳統的寫法和ES6中的寫法,把變量作為person對象的屬性值。第一種寫法大家很熟悉,使用鍵值對的表示法,而ES6中的新寫法只是簡單地用兩個變量名即可,而得到的結果跟傳統的寫法一樣。

這也就是新的寫法更簡捷了,變量名可以作為鍵值對的鍵(變量名name和age),而變量的名作為值(變量的值Zhangsan和12),最後一起組成了person對象的內容{name:”Zhangsan”,age:12}。

對象的屬性可以這樣簡寫,那麽對象的方法表示呢?

我們來講解方法的簡寫表示法:

 1     //傳統的表示法
 2     var person = {
3 say:function(){ 4 alert(‘這是傳統的表示法‘); 5 } 6 }; 7 8 //ES6的表示法 9 var person = { 10 say(){ 11 alert(‘這是ES6的表示法‘); 12 } 13 };

通過上面的案例,可以看出兩種寫法的區別,不管是屬性還是方法,確實ES6給我們帶來的表示法更加簡捷,代碼量更少。

屬性名可以是表達式

在表示法上除了這點改進以外,還有另外一個新特點:用字面量定義一個對象的時候,可以用表達式作為對象的屬性名或者方法名。不太明白?沒關系,來看小案例:

 1 var f = "first";
 2     var n = "Name";
 3     var s = "say";
 4     var h = "Hello";
 5 
 6     var person = {
 7         [ f+n ] : "Zhang",
 8         [ s+h ](){
 9             return "你好嗎?";
10         }
11     };
12     console.log(person.firstName);
13     //結果:Zhang
14     console.log(person.sayHello());
15     //結果:你好嗎?

註意上面person對象的定義,其中屬性名和方法名都是用中括號[ ]包裹著,裏面都是一個字符串相加的表達式,這就告訴我們,用字面量(大括號{ })定義對象的時候,屬性名和方法名可以是一個表達式,表達式的運算結果就是屬性名或者方法名。這點改進會使得對象在實際開發中的使用變得更加的靈活方便,贊!

介紹了對象的新的表示法,下面來介紹幾個ES6為對象新增的函數。

Object.is( )函數

函數的作用:比較兩個值是否嚴格相等,或者說全等。

也許有的初學者還不是很理解嚴格相等,我們在這裏來擴展一下:

嚴格相等和抽象相等

我們看看兩者的區別:

 1 var str = ‘12‘;
 2     var num = 12;
 3 
 4     //抽象相等
 5     str == num;
 6     //結果:true
 7 
 8 
 9     //嚴格相等
10     str === num;
11     //結果:false

可以看到,抽象相等用“==”表示,嚴格相等用|“===”表示,進行嚴格相等判斷的時候,首先要求類型是一樣的,否則會直接返回false。

所以上面的例子中,變量str和變量num一個是字符串類型,一個是數字類型,所以結果是false,而抽象相等會對類型不一致的兩個變量進行類型轉化,轉成同一類型再進行判斷。“12”轉換成數字類型得到12,再進行比較後得到的結果是true。

好了,科普完嚴格相等後我們回來看Object.is()函數,它的作用也跟嚴格相等一樣,我們來看看:

1 var str = ‘12‘;
2     var num = 12;
3     var num2 = 12;
4 
5     Object.is(str,num);
6     //結果:false
7 
8     Object.is(num2,num);
9     //結果:true

上述的執行結果跟我們預期的一樣,參數類型不一樣str和num進行比較,得到的結果是false。變量類型和值都一樣的num和num2進行比較,得到的結果是true。

Object.assign()函數

函數作用:將源對象的屬性賦值到目標對象上。這麽講肯定是有點抽象的,咱們用案例說話,更直觀更形象:

 1  //這個充當目標對象
 2     let target = {"a":1};
 3 
 4     //這個充當源對象
 5     let origin = {"b":2,"c":3};
 6 
 7     Object.assign(target,origin);
 8 
 9     //打印target對象出來看一下
10     console.log(target);
11     //結果 {a: 1, b: 2, c: 3}
12  

註意輸出的結果,target對象已經不是{ a:1 }了,而是變成了{a: 1, b: 2, c: 3},經過Object.assign( )函數的處理,源對象的屬性被添加到了target對象上。這就是Object.assign( )函數的作用。

此外,Object.assign( )函數的參數還可以是多個(至少是兩個)。我們在上面的案例稍做修改,加一個參數:

 1  //這個充當目標對象
 2     let target = {"a":1};
 3 
 4     //這個充當源對象
 5     let origin1 = {"b":2,"c":3};
 6 
 7     //這個充當源對象
 8     let origin2 = {"d":4,"e":5};
 9 
10     Object.assign(target,origin1,origin2);
11 
12     //打印target對象出來看一下
13     console.log(target);
14     //結果 {a: 1, b: 2, c: 3, d: 4, e: 5}
15  

我們從最後打印出來的結果可以看出,對象origin1和對象origin2的屬性都被添加賦值到了對象target上。也就是Object.assign( )函數參數中的源對象可以是一個或者一個以上。

那麽,如果賦值過程中,對象的屬性出現了相同的名字怎麽辦?如果這樣,後面的屬性值就會覆蓋前面的屬性值。還是上面的案例稍做修改,看代碼:

 1  //這個充當目標對象
 2     let target = {"a":1};
 3 
 4     //這個充當源對象
 5     let origin1 = {"a":2};
 6 
 7     //這個充當源對象
 8     let origin2 = {"a":3};
 9 
10     Object.assign(target,origin1,origin2);
11 
12     //打印target對象出來看一下
13     console.log(target);
14     //結果 {a: 3}
15  

每個對象屬性都含有屬性a,它的值從1到最後變成了3,也就是Object.assign()函數處理的過程中,會把最後出現的屬性覆蓋前面的同名屬性。

巧妙利用Object.assign( )函數的功能,我們可以完成很多效果,比如:給對象添加屬性和方法,克隆對象,合並多個對象,為對象的屬性指定默認值。

Object.getPrototypeOf( )函數

函數作用:獲取一個對象的prototype屬性。這裏的對象我們用一個自定義類實例出來的對象來演示。(這裏涉及到了javascript的面向對象,後面拓展)

 1  //自定義一個Person類(函數)
 2     function Person(){
 3 
 4     }
 5     //函數都有一個預屬性prototype對象
 6     Person.prototype = {
 7         //給prototype對象添加一個say方法
 8         say(){
 9             console.log(‘hello‘);
10         }
11     };
12 
13 
14     //實例化Person對象,賦值給變量allen
15     let allen = new Person();
16     //調用類的say方法
17     allen.say();
18     //結果:打印出hello
19 
20     //獲取allen對象的prototype屬性
21     Object.getPrototypeOf(allen);
22     //結果:打印{say:function(){.....}}

這個案例代碼有點長,但是為了大家能看懂,我把註釋寫得比較詳細,前面部分都是關於面向對象的實現。把函數Person用new關鍵字調用,這個時候函數Person就相當於構造函數或者說是一個類,實例化後是一個對象,這個對象會繼承Person類的prototype的屬性和方法。上述例子中,也就是對象allen繼承了一個say方法,可以直接調用。

如果你想看看prototype中還有哪些方法和屬性,那麽,你就可以使用Object.getPrototypeOf( )函數來獲取,參數就是allen對象,最後的結果也如我們所料,確實打印出了我們剛開始定義好的內容:一個對象,含有一個say方法{say:function(){.....}}。

那麽,如果我想為這個對象修改prototype的內容,要怎麽辦?這個時候,我們可以用ES6給我們的另一個方法。

Object.setPrototypeOf()函數

函數作用:設置一個對象的prototype屬性。

還是上面的案例, 我們稍做修改:

 1     //自定義一個Person類(函數)
 2     function Person(){
 3 
 4     }
 5     //函數都有一個預屬性prototype對象
 6     Person.prototype = {
 7         //給prototype對象添加一個say方法
 8         say(){
 9             console.log(‘hello‘);
10         }
11     };
12 
13 
14     //實例化Person對象,賦值給變量allen
15     let allen = new Person();
16     //調用類的say方法
17     allen.say();
18     //結果:打印出hello
19 
20 
21     //使用Object.setPrototypeOf
22     Object.setPrototypeOf(
23             allen,
24             {say(){console.log(‘hi‘)}
25     });
26 
27     //再次調用類的say方法
28     allen.say();
29     //結果:打印出hi

上面的代碼,我們使用Object.setPrototypeOf()函數對對象的prototype屬性進行了修改,具體的修改是重寫了say方法。在修改前,我們曾經調用過一次say( )方法,得到的結果是打印hello,修改之後我們再一次調用allen.say( );得到的結果是打印出hi,說明我們修改成功了。

最後兩個函數Object.getPrototypeOf()和Object.setPrototypeOf()的案例代碼有點長,涉及到了javascript的面向對象內容。新手如果沒有接觸過面向對象的話,讀起來一定會懵逼,這裏有必要拓展一下javascript的面向對象。

javascript的面向對象

Javascript本身不是一種面向對象的編程語言,在ES5中,它的語法中也沒有class(類的關鍵字),但是,開發者可以利用對象的原型prototype屬性來模擬面向對象進行編程開發。

這裏對於新手來說不一定可以理解,但沒關系,前端君就是負責把它講明白。下面我們就用prototype模式,簡單演示一下如何模擬面向對象編程:

 1 //構造函數模擬創建一個Dog類
 2     function Dog(name){
 3         this.name = name;
 4     }
 5 
 6     //把一些屬性和方法,定義在prototype對象上
 7     Dog.prototype = {
 8         "type":"動物",
 9         "say":function(){
10             alert("名字叫"+this.name);
11         }
12     };
13 
14     //實例化
15     var dog = new Dog(‘旺財‘);
16     //調用say方法
17     dog.say();
18     //結果:名字叫旺財

上面的案例告訴我們,模擬面向對象編程有幾個關鍵步驟:1、構造函數;2、給prototype對象添加屬性和方法;3、實例化;4、通過實例化後的對象調用類的方法或者屬性。

註意:面向對象是一種編程思想,並不是具體的工具。

本節小結

總結:ES6給我們帶來的新特性包括:簡潔的表示法、屬性名方法可以是表達式、Object.is( ) 函數、Object.assgin( ) 函數、Object.setPrototypeOf( ) 函數,Object.getPrototypeOf() 函數;此外還拓展了:嚴格相等和抽象相等的區別、javascript面向對象的實現。

ES6對象的擴展