首页 > 代码库 > ES6对象的扩展
ES6对象的扩展
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对象的扩展