zoukankan      html  css  js  c++  java
  • ES6-Object‘s Extends

    依赖文件地址 :https://github.com/chanceLe/ES6-Basic-Syntax/tree/master/js

      1 <!DOCTYPE html>
      2 <html>
      3     <head>
      4         <meta charset="UTF-8">
      5         <title>[es6]-08-对象的扩展</title>
      6         <script src="./js/browser.js"></script>
      7         <script type="text/babel">
      8             /*
      9              *  对象的扩展
     10              */
     11             
     12             /*属性的简洁表示法
     13              * ES6允许直接写入变量和函数,作为对象的属性和方法。
     14              * 这样书写更加简洁。
     15             */
     16             
     17             var foo = 'bar';
     18             var baz = {foo};
     19             console.log(baz);
     20             //等同于
     21             
     22             var baz2 = {foo:foo};
     23             /*
     24              * 上面代码表明,ES6允许在对象之中,只写属性名,不写属性值。
     25              * 这时,属性值等于属性名所代表的变量。下面还有个例子:
     26              */
     27             function f(x,y){
     28                 return {x,y}
     29             }
     30             //等价于
     31             function f1(x,y){
     32                 return {x:x,y:y}
     33             }
     34             console.log(f(1,2));
     35             // 方法也可以简写
     36             var o = {
     37                 method(){
     38                     return "hello!";
     39                 }
     40             }
     41             console.log(o.method());   //hello!
     42             //下面是一个实际的例子
     43             var birth = '2000/01/01';
     44             var Person = {
     45                 name:"zhangdan",
     46                 birth,
     47                 hello(){
     48                     console.log("my name is ",this.name);
     49                 }
     50             }
     51             Person.hello();
     52             //这种写法用于函数的返回值,将会非常方便。
     53             function getPoint(){
     54                 var x=1;
     55                 var y=10;
     56                 return {x,y};
     57             }
     58             console.log(getPoint());
     59             
     60             //CommonJS模块输出变量,就非常合适使用简洁写法。
     61             var ms = {};
     62             function getItem(key){
     63                 return key in ms? ms[key]:null;
     64             }
     65             function setItem(key,value){
     66                 ms[key] = value;
     67             }
     68             function clear(){
     69                 ms = {};
     70             }
     71             //module.exports = {getItem,setItem,clear};
     72             //等价于
     73             /*module.exports = {
     74                 getItem:getItem,
     75                 setItem:setItem,
     76                 clear:clear
     77             }
     78             */
     79             //注意简洁写法的属性名总是字符串,这会导致一些看上去比较奇怪的结果。
     80             var obj = {
     81                 class(){
     82                     console.log("class");
     83                 }
     84             }
     85             //上面代码中,class是字符串,所以不会因为它属于关键字,而导致语法解析报错。
     86             //如果某个方法的值是一个Generator函数,前面需要加上星号。
     87             /*
     88             var obj = {
     89                 * m(){
     90                     yield "hello world!";
     91                 }
     92             }
     93             console.log(obj.m(),"haha");
     94             */
     95             //上面的代码中,报错???
     96             
     97             /*
     98              * 属性名表达式
     99              * js语言定义对象的属性,有两种方法:
    100              * obj.foo = true;
    101              * obj["a"+"bc"] = 123;
    102              * 方法一直接用标识符作为属性名,方法二是用表达式作为属性名,这时要将表达式放在[]内。
    103              * 但是,如果使用字面量方式定义对象(使用大括号),在es5中只能使用方法一(标识符)定义属性。
    104              * 
    105              * es6允许字面量定义对象时,用方法二(表达式)作为对象的属性名,即把表达式放在[]内。
    106              */
    107             let propKey = "foo";
    108             let obj2 = {
    109                 [propKey]:true,
    110                 ['a'+'bc']:123
    111             }
    112             console.log(obj2);
    113             //表达式还可用于定义方法名。
    114             let obj3={
    115                 ["h"+"ello"](){
    116                     return "hi";
    117                 }
    118             }
    119             console.log(obj3.hello());
    120             //属性名表达式与简洁表示法,不能同时使用会报错。
    121             
    122             /*
    123              * 方法的name属性
    124              * 函数的name属性,返回函数名。对象方法也是函数,因此也有name属性。
    125              */
    126             var person = {
    127                 sayName(){
    128                     console.log(this.name);
    129                 },
    130                 firstName(){
    131                     return "nicholas"
    132                 }
    133             }
    134             console.log(person.sayName.name);
    135             console.log(person.firstName.name);
    136             //上面代码中,方法的name属性返回函数名。
    137             //如果使用了取值函数,则会在方法前加上get,
    138              // 存值函数,会加上set。(但是,实际上,我并没能分出来这个区别。)
    139              
    140              //两种特殊情况:bind方法创造的函数,name属性返回bound+函数名,
    141              //             Function构造函数创造的函数,name属性返回anonymous。
    142              console.log((new Function()).name);  //anonymous。
    143              var doSomething = function(){} 
    144              console.log(doSomething.bind().name);  //bound doSomething
    145              
    146              //如果对象的方法是一个Symbol值,namname属性返回这个Symbol值的描述。
    147              const key1 = Symbol("description");
    148              const key2 = Symbol();
    149              let obj4 = {
    150                  [key1](){},
    151                  [key2](){}
    152              }
    153              console.log(obj4[key1].name);  //''
    154              console.log(obj4[key2].name);  //''
    155              //事实上,打出来是完全一样的,???
    156              
    157              /*
    158               * Object.is()
    159               * es5可以通过下面的代码,部署Object.is()
    160               */
    161              Object.defineProperty(Object,"is",{
    162                  value:function(x,y){
    163                      if(x===y){
    164                          //针对+0不等于-0的情况
    165                          return x!==0 || 1/x === 1/y;
    166                      }
    167                      //针对NaN的情况
    168                      return x !==x && y!==y;
    169                  },
    170                  configurable:true,
    171                  enumerable:false,
    172                  writable:true
    173              })
    174              
    175              /*
    176               * Object.assign()
    177               * 该方法用于对象的合并,将源对象的所有可枚举属性,复制到目标
    178               * 对象。
    179               * 第一个参数是目标对象,剩下的参数都是源对象。
    180               * 如果有同名属性,后面的属性会覆盖前面的属性。
    181               * 如果只有一个参数,就返回这个参数。如果这个参数不是对象,会先转换成对象。
    182               * 由于undefined和null无法转成对象,所以他们作为参数会报错。
    183               * 
    184               * 如果非对象出现在源对象的位置(即非首参数),首先这些参数都会转成对象,如果
    185               * 无法转成对象,就会跳过。这意味着如果undefined和null不在首参数,就不会报错。
    186               * 
    187               * 其他类型的值,不在首参数也不会报错,但只有字符串会合入目标对象,数值和布尔值都会被
    188               * 忽略,因为只有字符串的包装对象会产生可枚举的实义属性。数值和布尔值转成的包装对象
    189               * 他们的原始值都存放在[[PrimitiveValue]]:"false"属性中。不会被Object.aasign()拷贝。
    190               * 
    191               * Object.assgn()不拷贝继承属性,也不拷贝不可枚举属性(enumerable:false)
    192               */
    193              var target = {a:1};
    194              var source1 = {b:2};
    195              var source2 = {c:3};
    196              var source3 = {b:5};
    197              Object.assign(target,source1,source2,source3);
    198              console.log(target);
    199              console.log(Object.assign(target) === target);  //true
    200              
    201              console.log(Object.assign({a:"b"},{[Symbol("c")]:"d"}));
    202              //结果显示属性名为Symbol值的属性,也会被Object.assign拷贝。
    203              
    204              //注意点,Object.assign()方法实行的是浅拷贝,也就是说,如果属性值是一个对象,那么目标对象拷贝到的
    205              //是这个对象的引用。
    206              //对于嵌套的对象,一旦遇到同名属性,Object.assign()的处理方法是替换,而不是添加。
    207              
    208              //Object.assign()可以用来处理数组,但是会把数组当做对象,并且一定会覆盖索引相同的值.
    209              console.log(Object.assign([1,2,3],[4,5]));   //[4,5,3]
    210              
    211              /*
    212               * 用途: 1.为对象添加属性  2.为对象添加方法  3.克隆对象
    213               * 4.将多个对象合并到某个对象。
    214               * 5.为属性指定默认值,这个跟jquery插件开发的那个东西一样。
    215               */
    216              function clone(origin){
    217                  return Object.assign({},origin);
    218              }
    219              //上面代码将原始对象拷贝到一个空对象,就得到了原始对象的克隆。不过上面这种不能克隆继承的值,如果
    220              //要保持继承链,可以用下面的代码:
    221              
    222              function clone2(origin){
    223                  let originProto = Object.getprototypeOf(origin);
    224                  return Object.assign(Object.create(originProto),origin);
    225              }
    226              
    227              
    228              /*
    229               * 属性的可枚举性。
    230               * 对象的每个属性都有一个描述对象,用来控制该属性的行为。
    231               * Object.getOwnPropertyDescriptor方法可以获取该属性的描述对象。
    232               */
    233              let obj5 = {foo:123};
    234              console.log(Object.getOwnPropertyDescriptor(obj5,'foo'));
    235              /*
    236               * 描述对象的enumerable就是可枚举性,es5有三个操作会忽略enumerable:false的属性:
    237               * for...in...循环:只遍历对象自身的和继承的可枚举属性。
    238               * Object.keys() 返回对象自身的所有可枚举属性的键名
    239               * JSON.stringify():只串行化对象自身的可枚举属性
    240               * 
    241               * ES6新增的Object.assign会忽略enumerable:false的属性。
    242               * 这四个操作中,只有for...in...会返回继承的属性。
    243               * 另外,ES6规定,所有class的原型的方法都是不可枚举的。
    244               */
    245              let k = Object.getOwnPropertyDescriptor(class {foo(){}}.prototype,"foo").enumerable;
    246              console.log(k);  //false  
    247              
    248              //总的来说,操作中引入继承的属性会让问题复杂化,大多数时候,我们只关心对象自身的属性。
    249              //所以,尽量不要用for...in...循环,而用Object.keys()代替。
    250              
    251              /*
    252               * 属性的遍历
    253               * ES6一共有5种方法遍历对象的属性。
    254               * 1.for...in   :循环遍历对象自身的和继承的可枚举属性(不含Symbol属性)。
    255               * 2.Object.keys(obj) : 返回一个数组,包括对象自身的(不含继承的)所有可枚举属性(不含Symbol属性)。
    256               * 3.Object.getOwnpropertyNames(obj)  :返回一个数组,包含对象自身的所有属性(不含Symbol属性,但是包括不可枚举属性)。
    257               * 4.Object.getOwnPropertySymbols(obj)  : 返回一个数组,包含对象自身的所有Symbol属性。
    258               * 5.Reflect.ownKeys(obj)  :返回一个数组,包含对象自身的所有属性,不管属性名是Symbol或字符串,也不管是否可枚举。
    259               * 
    260               * 以上5种方法遍历对象的属性,都遵守同样的属性遍历次序规则:
    261               *  首先遍历所有属性名为数值的属性,按照数字排序。
    262               *   其次遍历所有属性为字符串的属性,按照生成时间排序。
    263               *    最后遍历所有属性名为Symbol值的属性,按照生成时间排序。
    264               * 下面有个例子:
    265               */
    266              let m = Reflect.ownKeys({[Symbol()]:0,b:0,10:0,2:0,a:0});
    267              console.log(m);  //结果体现了遍历的次序规则。
    268              
    269          //_proto__属性,Object.setPrototypeOf()和Object.getprototypeOf()    
    270              /*
    271               * __proto__属性,用来设置或读取当前对象的prototype对象。目前所有浏览器(包括IE11)都部署了这个属性。
    272               */
    273              
    274              /*
    275              //es6的写法
    276              var obj6 = {
    277                  method(){}
    278              }
    279              obj6.__proto__ = someOtherObj;
    280              
    281              //es5的写法
    282              var obj7 = Object.create(someOtherObj);
    283              obj.method = function(){}
    284              */
    285              /*
    286               * 该属性没有写入es6的正文,而是写入了附录,原因是双下划线说明它本质上是一个内部属性。而不是一个正式的对外的API,
    287               * 只是由于浏览器的广泛支持,才被加入ES6。标准明确规定,只有浏览器必须部署这个属性,其他环境不一定要部署,而且新的
    288               * 代码最好是认为这个属性不存在的。因此最好不要使用这个属性,而是用下面的Object.setprototypeOf()Object.getprototypeOf()
    289               * 和Object.create()代替。
    290               * 
    291               * 在实现上,__proto__调用的是Object.prototype.__proto__。
    292               * 如果一个对象部署了__proto__属性,该属性的值就是对象的原型。
    293               */
    294              
    295              /*
    296               * Object.setPrototypeOf()
    297               * 作用与__proto__相同,是es6官方推荐的设置对象原型的方法。
    298               * 格式: Object.setPrototypeOf(object,prototype);
    299               * 下面是一个例子:
    300               */
    301              let proto = {};
    302              let obj8 = {x:10};
    303              Object.setPrototypeOf(obj8,proto);
    304              proto.y = 20; proto.z = 25;
    305              console.log(obj8.x,obj8.y,obj8.z) ;  //10,20,25
    306              
    307              /*
    308               * Object.getPrototypeOf()与上一个配套,用于读取一个对象的prototype对象。
    309               */
    310              console.log(Object.getPrototypeOf(obj8));  
    311         </script>
    312     </head>
    313     <body>
    314     </body>
    315 </html>
  • 相关阅读:
    【IT学习资源】2013.10.30
    【转载】 Bash之read命令
    【书本目录】 -- ABS(advanced bash scripts)
    【转载】vSphere的使用
    【转载】 Linux命令 -- tr 转换字符
    【转载】Oracle的日常监控脚本
    【转载】Nginx基础:6.webcache缓存服务
    大学记忆(3)[三国杀(终)]
    大学记忆(1)[记忆之殇]
    大学记忆(2)[计算机]
  • 原文地址:https://www.cnblogs.com/chengyunshen/p/7191647.html
Copyright © 2011-2022 走看看