zoukankan      html  css  js  c++  java
  • ES6对象属性名简洁表示法和表达式、对象新方法、属性的遍历

    概览

    对象属性的简洁表示法

    ES6允许直接写入变量和函数作为对象的属性和方法。
    ES6允许在对象中只写属性名,不写属性值。

    let foo = 'bar';
    let baz = {foo};
    console.log(baz); // {foo:'bar'}
    // same as
    let baz1 = {foo:foo}
    console.log(baz1); // {foo:'bar'}
    
    let first = 'Jone';
    let last = 'Doe';
    let obj = {first,last};
    console.log(obj); // {first: "Jone", last: "Doe"}
    // same as
    let obj1 = {first:first,last:last};
    console.log(obj1); // {first: "Jone", last: "Doe"}
    
    const HELLO = {
      method(){
        return 'hello'
      }
    }
    console.log(HELLO.method()); // 'hello'
    // same as
    const HELLO1 = {
      method:function(){
        return 'hello'
      }
    }
    console.log(HELLO1.method()); // 'hello'
    

    实际运用中的一些例子:

    // 用于人物名称及行为的对象
    let birth = '2000/01/01'
    const PERSON = {
      name: '张三',
      birth, // same as: birth:birth
      hello() {console.log('我的名字是', this.name);}
      // same as: hello:function(){...}
    }
    
    // 用于函数返回值
    function getPoint(x = 1, y=10){
      return {x, y}
    }
    console.log(getPoint()); // {x: 1, y: 10}
    console.log(getPoint(3,3)); // {x: 3, y: 3}
    console.log(getPoint(3)); // {x: 3, y: 10}
    
    // CommonJS模块输出变量
    let ms = {};
    function getItem(key){
      return key in ms? ms[key] : null;
    }
    function setItem(key,value){
      ms[key] = value;
    }
    function clear(){
      ms = {};
    }
    module.exports = {getItem,setItem,clear};
    // same as: module.exports = {getItem:getItem,setItem:setItem,clear:clear};
    
    // 属性的赋值器和取值器
    const CART = {
      _wheels: 4,
      get wheels(){
        return this._wheels;
      },
      set wheels(value){
        if(value<this._wheels){
          throw new Error('数值太小了');
        }
        this._wheels = value;
      }
    }
    

    属性名表达式

    ES6允许字面量定义对象时,用表达式作为对象的属性名,即把表达式放在方括号内。

    定义对象属性的两种方法:

    • 通过固定名称
    let obj = {};
    obj.foo = true;
    console.log(obj); // {foo: true}
    
    • 通过表达式
    let obj1 = {};
    obj1['a'+'bc'] = 123;
    console.log(obj1); // {abc: 123}
    
    let propKey = 'foo';
    let propKeyObj = {
      [propKey]: true,
      ['a'+ 'bc']: 123
    }
    console.log(propKeyObj); // {foo: true, abc: 123}
    
    let lastWord = 'last word';
    let a = {
      'first word':'hello',
      [lastWord]:'world'
    }
    console.log(a); // {first word: "hello", last word: "world"}
    console.log(a['first word']);// 'hello'
    console.log(a[lastWord]); // 'world'
    console.log(a['last word']); // 'world'
    
    // 定义方法名
    let methodName = {
      ['h'+'ello'](){
        return 'hi'
      }
    }
    console.log(methodName.hello()); // 'hi'
    

    注意:属性名表达式不能和简洁表达式同时使用

    // 报错
    let foo = 'bar';
    let bar = 'abc';
    let baz = {[foo]};
    

    注意:属性表达式如果是一个对象,默认情况下会把对象转为字符串[object Object]

    const keyA = {a:1};
    const keyB = {b:2};
    const myObject = {
      [keyA]: 'valueA',
      [keyB]: 'valueB',
    }
    console.log(myObject); // {[object Object]: "valueB"}
    

    Object.is(value1,value2)

    与严格相等运算符(=)的行为基本一致;
    解决严格运算符(
    =)NaN不等于自身,以及+0等于-0的问题。

    console.log(Object.is('foo','foo'));; // true
    
    console.log({} === {}); // false
    console.log(Object.is({},{})); // false
    
    console.log(NaN === NaN); // false
    console.log(Object.is(NaN,NaN)); // true
    
    console.log(+0 === -0); // true
    console.log(Object.is(+0,-0)); // false
    
    console.log([0,NaN,2].indexOf(NaN)); // -1
    console.log([0,NaN,2].findIndex(x => Object.is(x, NaN))); // 1
    

    Object.assign(target,source_1,source_2,...)

    Object.assign()方法将源对象(source)所有可枚举的属性合并到目标对象(target)中:它修改target,首先将source_1的所有可枚举的自己的属性复制到target中,然后将source_2的所有自己的属性复制到target中,以此类推。最后,它返回target。

    let target = {a:1};
    let source_1 = {b:2};
    let source_2 = {c:3};
    Object.assign(target,source_1,source_2);
    console.log(target,source_1,source_2); // {a: 1, b: 2, c: 3} {b: 2} {c: 3}
    

    让我们更仔细看看Object.assign()是如何运作的:

    • 两种类型的属性键:同时支持StringSymbel作为属性键;
    let v1 = 'abc';
    let v2 = true;
    let v3 = 10;
    let v4 = {[Symbol('c')]: 'c'};
    const obj = Object.assign({}, v1, v2, v3, v4);
    console.log(obj); // {0: "a", 1: "b", 2: "c", Symbol(c): "c"}
    
    • 仅复制源对象可枚举的自身属性:不复制继承属性,也不复制不可枚举的属性;
    const obj = Object.assign({b: 'c'},
        Object.defineProperty({}, 'invisible',{
          enumerable:false, // enumerable属性称为‘可枚举性’
          value:'hello'
        })
    )
    console.log(obj); // {b: "c"}
    
    • 通过赋值复制:目标对象中的属性是通过赋值(内部操作[[Put]])创建的。这意味着,如果target拥有(自己的或继承的)setter,则在复制期间将调用这些setter。另一种方法是定义新的属性,这是一种总是创建新的自己的属性且从不调用setter的操作。最初有人建议使用Object.assign()的一个变体,它使用定义而不是赋值的方式。这个提议在ECMAScript 6中已经被拒绝了,但是在以后的版本中可能会被重新考虑。
    let obj1 = {a: {b: 1}};
    let obj2 = Object.assign({}, obj1);
    console.log(obj2); // {a: {b: 1}} 
    
    // Object.assign()方法实行的是浅复制,而不是深复制。
    let target = {a: { b: 'c', d: 'e' }};
    let source = {a: { b: 'hello' }};
    const obj = Object.assign(target, source);
    console.log(obj); // a: {b: "hello"}
    console.log(target); // a: {b: "hello"}
    

    常见用途:
    为对象添加属性

    class Point{
      constructor(x, y){
        Object.assign(this, {x, y});
      }
    }
    

    为对象添加方法

    function SomeClass(){
      
    }
    Object.assign(SomeClass.prototype, {
      someMethod(arg1,arg2){
        // ...
      },
      anotherMethod(){
        // ...
      }
    })
    console.dir(SomeClass);
    
    // same as
    SomeClass.prototype.someMethod = function(arg1, arg2){
      //...
    };
    SomeClass.prototype.anotherMethod = function(){
      //...
    }
    

    克隆对象

    // 克隆原始对象自身的值
    function clone1(origin){
      return Object.assign({}, origin);
    }
    
    // 克隆原始对象继承的值(保持继承链)
    function clone2(params) {
      let paramsProto = Object.getPrototypeOf(params);
      return Object.assigin(Object.create(paramsProto), params)
    }
    

    合并多个对象

    // 多个对象合并到target
    const merge1 = (target, ...sources) => Object.assign(target, ...sources);
    // 多对象合并返回新对象
    const merge2 = (...sources) => Object.assign({}, ...sources);
    

    为属性指定默认值

    const DEFAULTS = {
      logLevel: 0,
      output: 'html'
    };
    function processContent(options){
      options = Object.assign({},DEFAULTS,options);
      console.log(options);
    }
    processContent('abc'); // {0: "a", 1: "b", 2: "c", logLevel: 0, output: "html"}
    processContent({'abc':'abc'}); // {logLevel: 0, output: "html", abc: "abc"}
    

    属性的遍历

    for...inObject.keys(obj)Object.getOwnPropertyNames(obj)Object.getOwnPropertySymbels(obj)Reflect.ownKeys(obj)

    function allObj(){
      this.name = '张三'; // 自有属性
      this.age = '12'; // 自有属性
      this.invisible = {
        enumerable: false,
        value: 'hello'
      },
      this.invisible = {
        enumerable: false,
        value: 'hello'
      }
    }
    allObj.prototype.disEnum = {
      enumerable: false,
      value: 'disEnum'
    }
    allObj.prototype.Enum = {
      enumerable: true,
      value: 'Enum'
    }
    let obj = new allObj
    Object.assign(obj, {
      a: '1',
      b: '2',
      c: '3',
      [Symbol('c')]: 'c',
    })
    // let obj2 = Object.assign(obj1,
    //   Object.defineProperty({}, )
    // )
    Object.assign(obj,
      Object.defineProperty({}, 'visible',{
        enumerable: true,
        value: 'word'
      })
    )
    console.log(obj); // allObj {a: "1",age: "12",b: "2",c: "3",invisible: {enumerable: false,value: 'hello'},name: "张三",visible: "word",Symbol(c): "c",__proto__:Enum: {enumerable: true, value: "Enum"},disEnum: {enumerable: false, value: "disEnum"}}
    // for...in循环遍历对象自身的和继承的属性(不含Symbol属性)
    for(let key in obj){
      console.log(key);
      // name
      // age
      // invisible
      // a
      // b
      // c
      // invisible
      // visible
      // disEnum
      // Enum
    }
    
    // Object.keys()返回一个数组,包括对象自身(不含继承的)的所有属性(不含Symbol属性)
    console.log(Object.keys(obj)); // ["name", "age", "invisible", "a", "b", "c", "visible"]
    
    // Object.getOwnPropertyNames返回一个数组,包含对象自身的所有属性(不含Symbol属性,但是包括不可枚举属性 )
    console.log(Object.getOwnPropertyNames(obj)); // ["name", "age", "invisible", "a", "b", "c", "visible"]
    
    // Object.getOwnPropertySymbols() 返回一个数组,包含所有对象自身的所有Symbol属性
    console.log(Object.getOwnPropertySymbols(obj)); // [Symbol(c)]
    
    // Reflect.ownKeys()返回一个数组,包含对象自身的所有属性,不管属性名是Symbol还是字符串,也不管是否可枚举
    console.log(Reflect.ownKeys(obj)); // ["name", "age", "invisible", "a", "b", "c", "visible", Symbol(c)]
    

    ES6对象属性名简洁表示法和表达式、对象新方法、属性的遍历

  • 相关阅读:
    java jdbc笔记整理
    Spring IOC (构造器注入)
    WEB-INF目录与META-INF目录的作用[转]
    [转]LL(1)文法判别之First集合、Follow集合、Select集合求法
    java读取TXT文件的方法 (转)
    Ubuntu 12.04下搭建Web服务器 (MySQL+PHP+Apache)(转)
    题目:求1+2+…+n,要求不能使用乘除法、for、while、if、else、switch、case等关键字以及条件判断语句(A?B:C)
    error LNK2019: 无法解析的外部符号 _WinMain@16,该符号在函数 ___tmainCR...(转)
    汇编leal命令的灵活用法及理解
    C++之继承
  • 原文地址:https://www.cnblogs.com/yihan123/p/14634418.html
Copyright © 2011-2022 走看看