es6笔记3^_^object

Posted webNick

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了es6笔记3^_^object相关的知识,希望对你有一定的参考价值。

一、destructuring

  ES6允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构Destructuring。
//es5
if(1){
    let cat = \'ken\';
    let dog = \'lili\';
    let zoo = {cat: cat, dog: dog};
    console.log(zoo) ; //Object {cat: "ken", dog: "lili"}
}
//用ES6完全可以像下面这么写:
if(1){
    let cat = \'ken\';
    let dog = \'lili\';
    let zoo = {cat, dog};
    console.log(zoo) ; //Object {cat: "ken", dog: "lili"}
}
//反过来可以这么写:
if(1){
    let dog = {type: \'animal\', many: 2};
    let { type, many} = dog;
    console.log(type, many) ;  //animal 2
}

二、属性名表达式

  用方法、表达式作为对象的属性名;表达式还可以用于定义方法名。
  javascript语言定义对象的属性,有两种方法。
    let obj1 = {};
// 方法一
    obj1.foo = true;
// 方法二
    obj1[\'a\'+\'bc\'] = 123;
    console.log(obj1);
  上面代码的方法一是直接用标识符作为属性名,方法二是用表达式作为属性名,这时要将表达式放在方括号之内。
  如果使用字面量方式定义对象(使用大括号),在ES5中只能使用方法一(标识符)定义属性。
    var obj2 = {
        foo: true,
        abc: 123
    }
  ES6允许字面量定义对象时,用方法(表达式)作为对象的属性名,即把表达式放在方括号内。
    let propKey = \'foo\';
    let obj3 = {
        [propKey]: true,
        [\'a\'+\'bc\']: 123
    };
    console.log(obj3);
//表达式还可以用于定义方法名。
    let ello=\'i\';
    let obj4 = {
        [\'h\'+ello]() {
            return \'hi nick\';
        }
    };
    console.log(obj4.hi()); // hi nick

三、Object.is()

  Object.is()用来比较两个值是否严格相等。它与严格比较运算符(===)的行为基本一致,不同之处只有两个:一是+0不等于-0,二是NaN等于自身。
console.log(+0 === -0);//true
console.log(NaN === NaN); // false
console.log(Object.is(+0, -0)); // false
console.log(Object.is(NaN, NaN)); // true

四、Object.assign()

  Object.assign方法用来将源对象(source)的所有可枚举属性,复制到目标对象(target)。
  它至少需要两个对象作为参数,第一个参数是目标对象,后面的参数都是源对象。只要有一个参数不是对象,就会抛出TypeError错误。
    let target = { a: 1 };
    let source1 = { b: 2 };
    let source2 = { c: 3 };
    Object.assign(target, source1, source2);
    console.log(target); // {a:1, b:2, c:3}
注意:如果目标对象与源对象有同名属性,或多个源对象有同名属性,则后面的属性会覆盖前面的属性。
    let target1 = { a: 1, b: 1 };
    let source11 = { b: 2, c: 2 };
    let source21 = { c: 3 };

    Object.assign(target1, source11, source21);
    console.log(target1);  // {a:1, b:2, c:3}
    console.log(Object.assign({\'name\':\'张三\'},{\'name\':\'nick\',\'age\':26,\'sex\':\'男\',\'sex\':{\'gander\':\'handsome\'}}));
  Object.assign只拷贝自身属性,不可枚举的属性(enumerable为false)和继承的属性不会被拷贝。
     let  obj1=Object.assign({b: \'c\'},
                Object.defineProperty({}, \'invisible\', {
                    enumerable: false,
                    value: \'hello\'
                })
        );
        console.log(obj1);// { b: \'c\' }

    let obj2 =Object.assign({b: \'c\'},
            Object.defineProperty({}, \'invisible\', {
                enumerable: true,
                value: \'hello\'
            })
    );
    console.log(obj2);// {b: "c", invisible: "hello"}
  属性名为Symbol值的属性,也会被Object.assign拷贝。
    let obj3=Object.assign({ a: \'b\' }, { [Symbol(\'c\')]: \'d\' })
    console.log(obj3);// { a: \'b\', Symbol(c): \'d\' }
注意:Object.assign可以用来处理数组,但是会把数组视为对象。
Object.assign([1, 2, 3], [4, 5]);// [4, 5, 3]

  其中,4覆盖1,5覆盖2,因为它们在数组的同一位置,所以就对应位置覆盖了。  

  Object.assign还有很多用处,下面就看一下吧:   

  为对象添加属性

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

  这样就给Point类的对象实例添加了x、y属性。

  为对象添加方法

    let SomeClass={test:\'nick\'};
    SomeClass.prototype={};
    Object.assign(SomeClass.prototype, {
        someMethod:function(arg1, arg2) {

        },
        anotherMethod:function () {

        }
    });
    console.log(SomeClass);
  等同于下面的写法
    let SomeClass2={test:\'nick2\'};
    SomeClass2.prototype={};
    SomeClass2.prototype.someMethod = function (arg1, arg2) {

    };
    SomeClass2.prototype.anotherMethod = function () {

    };
    console.log(SomeClass2);

  上面代码使用了对象属性的简洁表示法,直接将两个函数放在大括号中,再使用assign方法添加到SomeClass.prototype之中。

  克隆对象

    function clone1(origin) {
        return Object.assign({}, origin);
    }
  上面代码将原始对象拷贝到一个空对象,就得到了原始对象的克隆。
  不过,采用这种方法克隆,只能克隆原始对象自身的值,不能克隆它继承的值。如果想要保持继承链,可以采用下面的代码。
function clone2(origin) {
    let originProto = Object.getPrototypeOf(origin);
    return Object.assign(Object.create(originProto), origin);
}

  在JS里子类利用Object.getPrototypeOf去调用父类方法,用来获取对象的原型。用它可以模仿Java的super。 

  多个对象合并到某个对象

    const merge1 =(target, ...sources) => Object.assign(target, ...sources);

  多个对象合并到一个新对象

    const merge2 = (...sources) => Object.assign({},...sources);

  为属性指定默认值

    const DEFAULTS = {
        logLevel: 0,
        outputFormat: \'html\'
    };

    function processContent(options) {
        let options1 = Object.assign({}, DEFAULTS, options);
    }
  上面代码中,DEFAULTS对象是默认值,options对象是用户提供的参数。Object.assign方法将DEFAULTS和options合并成一个新对象,如果两者有同名属性,则option的属性值会覆盖DEFAULTS的属性值。
注: 由于存在深拷贝的问题,DEFAULTS对象和options对象的所有属性的值,都只能是简单类型,而不能指向另一个对象。否则,将导致DEFAULTS对象的该属性不起作用。
此篇全部代码:
<!DOCTYPE html>
<html >
<head>
    <meta charset="UTF-8">
    <title>es6-object</title>
    <script>
/*object*/
//1.destructuring
//ES6允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构(Destructuring)。
//es5
if(1){
    let cat = \'ken\';
    let dog = \'lili\';
    let zoo = {cat: cat, dog: dog};
    console.log(zoo) ; //Object {cat: "ken", dog: "lili"}
}
//用ES6完全可以像下面这么写:
if(1){
    let cat = \'ken\';
    let dog = \'lili\';
    let zoo = {cat, dog};
    console.log(zoo) ; //Object {cat: "ken", dog: "lili"}
}
//反过来可以这么写:
if(1){
    let dog = {type: \'animal\', many: 2};
    let { type, many} = dog;
    console.log(type, many) ;  //animal 2
}

/*2.属性名表达式(用方法(表达式)作为对象的属性名;表达式还可以用于定义方法名。)
JavaScript语言定义对象的属性,有两种方法。*/
if(1){
    let obj1 = {};
// 方法一
    obj1.foo = true;
// 方法二
    obj1[\'a\'+\'bc\'] = 123;
    console.log(obj1);
    /*上面代码的方法一是直接用标识符作为属性名,方法二是用表达式作为属性名,这时要将表达式放在方括号之内。
     如果使用字面量方式定义对象(使用大括号),在ES5中只能使用方法一(标识符)定义属性。
    var obj2 = {
        foo: true,
        abc: 123
    };*/
//ES6允许字面量定义对象时,用方法(表达式)作为对象的属性名,即把表达式放在方括号内。
    let propKey = \'foo\';
    let obj3 = {
        [propKey]: true,
        [\'a\'+\'bc\']: 123
    };
    console.log(obj3);
//表达式还可以用于定义方法名。
    let ello=\'i\';
    let obj4 = {
        [\'h\'+ello]() {
            return \'hi nick\';
        }
    };
    console.log(obj4.hi()); // hi nick
}
//3. Object.is()用来比较两个值是否严格相等。它与严格比较运算符(===)的行为基本一致,不同之处只有两个:一是+0不等于-0,二是NaN等于自身。
console.log(+0 === -0);//true
console.log(NaN === NaN); // false
console.log(Object.is(+0, -0)); // false
console.log(Object.is(NaN, NaN)); // true
/*
4.源对象的所有可枚举属性,复制到目标对象
Object.assign方法用来将源对象(source)的所有可枚举属性,复制到目标对象(target)。
它至少需要两个对象作为参数,第一个参数是目标对象,后面的参数都是源对象。只要有一个参数不是对象,就会抛出TypeError错误。
*/
if(1){
    let target = { a: 1 };
    let source1 = { b: 2 };
    let source2 = { c: 3 };
    Object.assign(target, source1, source2);
    console.log(target); // {a:1, b:2, c:3}
//注意,如果目标对象与源对象有同名属性,或多个源对象有同名属性,则后面的属性会覆盖前面的属性。

    let target1 = { a: 1, b: 1 };
    let source11 = { b: 2, c: 2 };
    let source21 = { c: 3 };

    Object.assign(target1, source11, source21);
    console.log(target1);  // {a:1, b:2, c:3}
    console.log(Object.assign({\'name\':\'张三\'},{\'name\':\'nick\',\'age\':26,\'sex\':\'男\',\'sex\':{\'gander\':\'handsome\'}}));

//    Object.assign只拷贝自身属性,不可枚举的属性(enumerable为false)和继承的属性不会被拷贝。

     let  obj1=Object.assign({b: \'c\'},
                Object.defineProperty({}, \'invisible\', {
                    enumerable: false,
                    value: \'hello\'
                })
        );
        console.log(obj1);// { b: \'c\' }

    let obj2 =Object.assign({b: \'c\'},
            Object.defineProperty({}, \'invisible\', {
                enumerable: true,
                value: \'hello\'
            })
    );
    console.log(obj2);// {b: "c", invisible: "hello"}

//    属性名为Symbol值的属性,也会被Object.assign拷贝。
    let obj3=Object.assign({ a: \'b\' }, { [Symbol(\'c\')]: \'d\' })
    console.log(obj3);// { a: \'b\', Symbol(c): \'d\' }

//    注意,Object.assign可以用来处理数组,但是会把数组视为对象。
Object.assign([1, 2, 3], [4, 5]);// [4, 5, 3]

  /*  其中,4覆盖1,5覆盖2,因为它们在数组的同一位置,所以就对应位置覆盖了。
    Object.assign还有很多用处,下面就看一下吧:
    为对象添加属性
*/
    class Point {
        constructor(x, y) {
            Object.assign(this, {x, y});
        }
    }

    /*这样就给Point类的对象实例添加了x、y属性。
    为对象添加方法*/
    let SomeClass={test:\'nick\'};
    SomeClass.prototype={};
    Object.assign(SomeClass.prototype, {
        someMethod:function(arg1, arg2) {

        },
        anotherMethod:function () {

        }
    });
    console.log(SomeClass);
// 等同于下面的写法
    let SomeClass2={test:\'nick2\'};
    SomeClass2.prototype={};
    SomeClass2.prototype.someMethod = function (arg1, arg2) {

    };
    SomeClass2.prototype.anotherMethod = function () {

    };
    console.log(SomeClass2);

    /*上面代码使用了对象属性的简洁表示法,直接将两个函数放在大括号中,再使用assign方法添加到SomeClass.prototype之中。
    克隆对象*/

    function clone1(origin) {
        return Object.assign({}, origin);
    }
/*
    上面代码将原始对象拷贝到一个空对象,就得到了原始对象的克隆。
    不过,采用这种方法克隆,只能克隆原始对象自身的值,不能克隆它继承的值。如果想要保持继承链,可以采用下面的代码。*/

function clone2(origin) {
    let originProto = Object.getPrototypeOf(origin);
    return Object.assign(Object.create(originProto), origin);
}
  /*  在JS里子类利用Object.getPrototypeOf去调用父类方法,用来获取对象的原型。用它可以模仿Java的super。
    将多个对象合并成一个对象
    多个对象合并到某个对象*/

    const merge1 =(target, ...sources) => Object.assign(target, ...sources);

//    多个对象合并到一个新对象

    const merge2 = (...sources) => Object.assign({},...sources);

//    为属性指定默认值

    const DEFAULTS = {
        logLevel: 0,
        outputFormat: \'html\'
    };

    function processContent(options) {
        let options1 = Object.assign({}, DEFAULTS, options);
    }
/*
    上面代码中,DEFAULTS对象是默认值,options对象是用户提供的参数。Object.assign方法将DEFAULTS和options合并成一个新对象,如果两者有同名属性,则option的属性值会覆盖DEFAULTS的属性值。
注: 由于存在深拷贝的问题,DEFAULTS对象和options对象的所有属性的值,都只能是简单类型,而不能指向另一个对象。否则,将导致DEFAULTS对象的该属性不起作用。*/
}
/*
5.proto属性
proto属性,用来读取或设置当前对象的prototype对象。该属性一度被正式写入ES6草案,但后来又被移除(尽量别用)。目前,所有浏览器(包括IE11)都部署了这个属性。
*/
if(1){
// es6的写法
    let someOtherObj=function(){console.log(\'someOtherObj\');};
    let obj1 = {
        __proto__: someOtherObj,
        method: function() {console.log(\'method\');}
    };
// es5的写法
    let obj2 = Object.create(someOtherObj);
    obj2.method = function() {};
    console.log(obj1);
    console.log(obj2);
}
//    17.Symbol类型
//ES6引入了一种新的原始数据类型Symbol,表示独一无二的ID。凡是属性名属于Symbol类型,就都是独一无二的,可以保证不会与其他属性名产生冲突。
if(1){
    let s = Symbol();
    console.log(typeof s);// "symbol"
    /*
     typeof运算符的结果,表明变量s是Symbol数据类型,而不是字符串之类的其他类型。
     注意,Symbol函数前不能使用new命令,否则会报错。这是因为生成的Symbol是一个原始类型的值,不是对象。
     Symbol类型的值不能与其他类型的值进行运算,会报错。
     */

    let sym = Symbol(\'My symbol\');
//    "your symbol is " + sym
// TypeError: can\'t convert symbol to string
//            `your symbol is ${sym}`
// TypeError: can\'t convert symbol to string
//但是,Symbol类型的值可以转为字符串。
    console.log(String(sym)); // \'Symbol(My symbol)\'
    console.log(sym.toString()); // \'Symbol(My symbol)\'
}
/*
6.内置代理
Proxy 内置的一个代理工具,使用他可以在对象处理上加一层屏障:

S6原生提供Proxy构造函数,用来生成Proxy实例。

var proxy = new Proxy(target, handler)
new Proxy()表示生成一个Proxy实例,它的target参数表示所要拦截的目标对象,handler参数也是一个对象,用来定制拦截行为。
*/
if(1){
    let plain = {
        name : "hubwiz"
    };
    let proxy = new Proxy(plain, {
        get: function(target, property) {
            console.log(target);//plain
            console.log(property);//title
            return property in target ? target[property] : "汇智网";
        }
    });
    console.log(proxy.name);// "hubwiz"
    console.log(proxy.title);// "汇智网"
}
/*
Proxy(target, handler), 这里的 handler有如下的方法:
get(target, propKey, receiver):拦截对象属性的读取,比如proxy.foo和proxy[\'foo\'],返回类型不限。最后一个参数receiver可选,当target对象设置了propKey属性的get函数时,receiver对象会绑定get函数的this对象。
set(target, propKey, value, receiver):拦截对象属性的设置,比如proxy.foo = v或proxy[\'foo\'] = v,返回一个布尔值。
has(target, propKey):拦截propKey in proxy的操作,返回一个布尔值。
deleteProperty(target, propKey) :拦截delete proxy[propKey]的操作,返回一个布尔值。
enumerate(target):拦截for (var x in proxy),返回一个遍历器。
hasOwn(target, propKey):拦截proxy.hasOwnProperty(\'foo\'),返回一个布尔值。
ownKeys(target):拦截Object.getOwnPropertyNames(proxy)、Object.getOwnPropertySymbols(proxy)、Object.keys(proxy),返回一个数组。该方法返回对象所有自身的属性,而Object.keys()仅返回对象可遍历的属性。
getOwnPropertyDescriptor(target, propKey) :拦截Object.getOwnPropertyDescriptor(proxy, propKey),返回属性的描述对象。
defineProperty(target, propKey, propDesc):拦截Object.defineProperty(proxy, propKey, propDesc)、Object.defineProperties(proxy, propDescs),返回一个布尔值。
preventExtensions(target):拦截Object.preventExtensions(proxy),返回一个布尔值。
getPrototypeOf(target) :拦截Object.getPrototypeOf(proxy),返回一个对象。
isExtensible(target):拦截Object.isExtensible(proxy),返回一个布尔值。
setPrototypeOf(target, proto):拦截Object.setPrototypeOf(proxy, proto),返回一个布尔值。
如果目标对象是函数,那么还有两种额外操作可以拦截。
apply(target, object, args):拦截Proxy实例作为函数调用的操作,比如proxy(...args)、proxy.call(object, ...args)、proxy.apply(...)。
construct(target, args, proxy):拦截Proxy实例作为构造函数调用的操作,比如new proxy(...args)。
*/
</script>
</head>
<body>

</body>
</html>
View Code

此篇终,待续……

 

以上是关于es6笔记3^_^object的主要内容,如果未能解决你的问题,请参考以下文章

ES6 对象Object

ES6 对象Object

(_.merge in ES6/ES7)Object.assign 不覆盖未定义的值

es5_Object

es5_Object

ES6笔记-- Symbol类型