学习笔记——对象方法整理

在前面写过两篇文章,分别是关于数组和字符串的方法解析,那这三剑客之一的对象怎么能不写呢,本次来整理一下对象有哪些经常使用的方法,下面介绍的每一个方法都会写与示例,方便你们对照查看。^_^面试

对象是指: 成对的名称(字符串)与值(任何值),其中名称经过冒号与值分隔;segmentfault

1、建立对象的方式,如下列出了四种,可根据实际状况来选择

(1)字面量形式(最经常使用),在实际中运用较多,较方便,易上手:数组

let object={
    a:1,
    b:2
};
console.log(object);       //{a:1,b:2}
复制代码

(2)对象实例(传统的形式,在操做对象时用的较频繁。):bash

let object=new Object();
    object.a=1;
    object.b=2;
console.log(object);        //{a:1,b:2}
复制代码

(3)构造函数形式:微信

function employee(name,job,born) {
    this.name=name;
    this.job=job;
    this.born=born;
}
let bill=new employee("Bill Gates","Engineer",1985);
 
// employee {name: "Bill Gates", job: "Engineer", born: 1985} 
复制代码

(4)工厂模式:函数

工厂模式的优点是可以一次性出厂多个相同的属性的对象,节省资源占用,缺点是:属性都为相同的,若是要建立不一样的须要从新生成。工具

function create(name,job,born){
    let people=new Object();
    people.name=name;
    people.job=job;
    people.born=born;
    people.show=function(){
    console.log("name:"+this.name+","+"job:"+this.job+","+"born:"+this.born)
    };
    return people;
}
let friend=create("Christine","teacher","1990");
 
friend.show();  //name:Christine,job:teacher,born:1990
复制代码

(5)原型模式post

将属性赋值到对象的原型上,并不会影响其自己的属性。测试

function create(name,job,born){};
    create.prototype.name="Christine";
    create.prototype.job="teacher";
    create.prototype.born="1990";
    create.prototype.show=function(){
    console.log("name:"+this.name+","+"job:"+this.job+","+"born:"+this.born)
};
let friend=new create();
friend.show();   //name:Christine,job:teacher,born:1990
复制代码

(6)ES6 class模式ui

//定义类
    class Point {
            constructor(x, y) {
                this.x = x;
                this.y = y;
            };
            //定义方法
            toString() {
                return '(' + this.x + ', ' + this.y + ')';
            }
            multiplication() {
                return this.x * this.y
            }
            test() {
                return '1231354654'
            }
        }
        console.log(Point.name)  
        //Point (name属性老是返回紧跟在class关键字后面的类名。)
        
        // 实例化并调用(实例化和调用方法同es5相同)
        let x = new Point(5, 6)
        console.log(x.toString(), '相乘结果:' + x.multiplication(), x.test())
        // (5, 6) 相乘结果:30 1231354654
       
        // 快速添加方法到原型上 (以下图,直接可添加到原型)
        Object.assign(Point.prototype, {
            dosomething() { },
            toValue() { }
        });
        console.log(Point.prototype)
复制代码

2.Object.assign()浅拷贝 && JSON.parse(JSON.stringify())深拷贝

拷贝:其实就是一个对象复制给另一整个对象,让对象相互不影响。对象的拷贝又分为浅拷贝和深拷贝:对象的浅拷贝(只拷贝一层);对象的深拷贝(拷贝多层);

!注意:浅拷贝和深拷贝只针对object和Array这样的复杂的对象

Object.assign()方法用于将全部可枚举属性的值从一个或多个源对象复制到目标对象,它将返回目标对象。 Object.assign(target, ...sources)

参数:

target:目标对象;sources:源对象;返回值:目标对象。

例:

(1)用来复制一个新对象,并不会影响原对象

let obj = { a: 1 };
let copy = Object.assign({}, obj);
console.log(copy);    // { a: 1 }
复制代码

(2)用来合并对象属性,将源对象的全部可枚举属性,复制到目标对象。

//object.assign(obj, obj2)  obj2是源对象,obj 是目标对象,返回目标对象
 
let obj = { a: 1 };
let obj2={b:2};

console.log(Object.assign(obj,obj2)===obj);  //true,返回目标对象
console.log(obj);       //{a:1,b:2} obj的值已被更改
复制代码

(3)若是目标对象和源对象中有相同的键,则属性将被源对象的属性覆盖,后面的源属性会覆盖以前的相同键的源属性。

let obj = { a: 1 };
let obj2 = {a:5,b:2};
let obj3 = {b:1,d:0};
Object.assign(obj,obj2,obj3);

console.log(obj);       // {a: 5, b: 1, d: 0}
复制代码

obj和obj2同时拥有相同的键a,但两个值不一样,obj是目标对象,因此会被源对象obj2的值覆盖,obj2obj3也同时拥有相同的键b,在拷贝时,obj3排在obj2的后面,因此obj2被覆盖 ,最终打印结果是:{a:5,b:1,d:0}

(4)当assign只有一个对象时,则直接返回这个对象,不作任何操做;

let obj = { a: 1 }
Object.assign(obj);
console.log(obj);        //{a:1}
复制代码

(5)Object.assign()方法实行的是浅拷贝,而不是深拷贝。也就是说,若是源对象某个属性的值是对象,那么目标对象拷贝获得的是这个对象的引用。

let obj1 = { a: 0 , b: { c: 0}};
let obj2 = Object.assign({}, obj1);
obj1.b.c=5;

console.log(obj2)       //{a:0,b:{c:5}};
复制代码

当咱们在改变obj1的值时,并无想改变obj2,但obj2的值也发生了改变,这违背了咱们的想法。

(6)给当前的对象添加新的属性

对象尽可能静态化,一旦定义,就不得随意添加新的属性。若是添加属性不可避免,要使用Object.assign方法。

const a = {};
Object.assign(a, { x: 3 });  // a => x:3
复制代码

若是添加相同的属性,旧属性的值会被新的值覆盖:

const a = { x: 5 };
Object.assign(a, { x: 3 });  // a => x:3
复制代码

(7)JSON.parse(JSON.stringify())实现深拷贝

let obj1 = { a: 0 , b: { c: 0}};
let obj3 = JSON.parse(JSON.stringify(obj1));
obj1.a = 4;
obj1.b.c = 4;
console.log(obj3);     //{ a: 0 , b: { c: 0}};
复制代码

上述方法,大部分状况是能够解决,但有如下几种状况没法识别:

  1. 会忽略 undefined
  2. 会忽略 symbol
  3. 不能序列化函数
  4. 不能解决循环引用的对象

针对这几个问题,也不是没有解决方法,能够本身去实现一个深拷贝,但须要考虑各类类型以及边界值,我更推荐使用 lodash工具库的深拷贝函数cloneDeep()

3、Object.entries()

返回一个数组,其元素是与直接在object上找到的可枚举属性键值对相对应的数组。属性的顺序与经过手动循环对象的属性值所给出的顺序相同。

例: (1).当键值为正常字符时,返回的键的值为字符串

let obj1 = {a:1,b:2};
let obj2 = Object.entries(obj1);
console.log(obj2) ;       //  [ ["a":1],["b":2] ] 
复制代码

(2)当键值为数字时,返回的键的值也是字符串

let obj = { 0: 'a', 1: 'b', 2: 'c' };
console.log(Object.entries(obj));     // [ ['0', 'a'], ['1', 'b'], ['2', 'c'] ] 
复制代码

(3)当键值的数字错乱无序时,它会将其排序后返回

let anObj = { 100: 'a', 2: 'b', 9: 'c' };
console.log(Object.entries(anObj));   //[["2","b"],["9","c"],["100","a"]]
复制代码

(4)展开对象

const object1 = {
 a: 'somestring',
 b: 42
};

for (let [key, value] of Object.entries(object1)) {
 console.log(`${key}: ${value}`);
}
//     "a: somestring"
//     "b: 42"
复制代码

4、Object.is()方法判断两个值是不是相等的值

Object.is(value1, value2);

参数:

value1:须要比较的第一个值。 value2:须要比较的第二个值。 返回值:表示两个参数是否相同的Boolean

(1)比较字符串

比较字符串(单纯的比较字符串的每一位,若是彻底相同返回true,只要有一个不同,返回false)

Object.is('foo', 'foo’); //true; Object.is('fo', 'foo’);           //false
复制代码

(2)比较数组

比较数组 (对数组无感,即便是相同的数组,或者是相同的空数组,都返回false)

Object.is([11,12],[11,12]).        //false
 
Object.is([],[])                   //false 
复制代码

(3)比较window

Object.is(window, window)           //true
 
Object.is(window, document);       //false
复制代码

(4)比较特殊对象undifined 和null

undefinednull都等于它自己,但undefined不等于null

Object.is(null, null);              //true

Object.is(undefined,undefined);     //true
 
Object.is(undefined,null);          //false 
复制代码

(5)比较正常对象

let test={a:1,b:2};     

let test1={a:2,b:5};
 
Object.is(test,test1)            //false
----------------------------------------------------------
let test={a:1,b:2};              //比较的两端需为同样的元素,当一边为变量时,另外一边也必须是变量
 
Object.is(test,{a:1,b:2}).       //false
 
Object.is(test,test).            //true复制代码

五.Object.keys()

Object.keys()方法返回一个由一个给定对象的自身可枚举属性组成的数组,数组的属性的排列顺序和使用for..in循环遍历该对象时返回的顺序一致二者的主要区别是 一个 for-in循环还会枚举其原型链上的属性

Object.keys(obj)

参数

obj:要返回其枚举自身属性的对象。

返回值:一个表示给定对象的全部可枚举属性的字符串数组。

描述:Object.keys返回一个全部元素为字符串的数组,其元素来自于从给定的对象上面可直接枚举的属性。这些属性的顺序与手动遍历该对象属性时的一致。

(1)数组Array对象(返回索引值)

let arr=[1,2,3];            
Object.keys(arr)         //  ["0", "1", "2”] 复制代码

(2)object对象(返回key值)

let obj = { foo: "bar", baz: 42 };
Object.keys(obj)        //  ["foo", "baz”] 复制代码

(3)类数组,对象

let obj = { 0 : "a", 1 : "b", 2 : "c”}; Object.keys(obj) // ["0", "1", "2"] 复制代码

(4)类数组对象 随机key排序

let Obj = { 100: 'a’, 2: 'b’,7: 'c’ }; console.log(Object.keys(Obj)); // ['2', '7', '100’]. 返回从小到大排序后的结果
复制代码

六.obj.hasOwnProperty(key) 检测对象有没有指定的key

hasOwnProperty()方法会返回一个布尔值,指示对象是否具备指定的属性做为自身(不继承)属性。 obj.hasOwnProperty(prop)

参数

prop:要检测的属性 字符串 名称或者 Symbol

返回值:用来判断某个对象是否含有指定的属性的 Boolean

全部继承了 Object 的对象都会继承到 hasOwnProperty 方法。这个方法能够用来检测一个对象是否含有特定的自身属性;和 in 运算符不一样,该方法会忽略掉那些从原型链上继承到的属性。

let obj=new Object();
    obj.a=5;
    
console.log(obj.hasOwnProperty('a’)) // true delete obj.a; console.log(obj.hasOwnProperty(‘a’)). //false 复制代码

7、Object.values()

方法返回一个给定对象本身的全部可枚举属性值的数组,值的顺序与使用for..in循环相同,返回的对象的value值,与Object.key()相反

例: (1)正常对象

let obj={a:1,b:2,c:3};
console.log(Object.values(obj))         //  [1, 2, 3]
复制代码

(2)类数组对象

let obj ={0:'a',1:'b',2:'c'};
console.log(Object.values(obj)).       //  a,b,c
复制代码

(3) key值为无序number

let obj={100:'a',10:'b',1:'1'};
console.log(Object.values(obj)).   // ["1", "b", "a"]
复制代码

8、...扩展运算符

对象的扩展运算符(...)用于取出参数对象的全部可遍历属性,拷贝到当前对象之中。

let z = { a: 3, b: 4 };
let n = { ...z };     //  n =>  { a: 3, b: 4 }
复制代码

因为数组是特殊的对象,因此对象的扩展运算符也能够用于数组。

let foo = { ...['a', 'b', 'c'] };  //  foo=> {0: "a", 1: "b", 2: "c"}foo

复制代码

对象的扩展运算符等同于使用Object.assign()方法。可复制对象

let aClone = { ...a };
// 等同于
let aClone = Object.assign({}, a);

-------

let z = { a: 3, b: 4 };
let n = { ...z };  // n => {a: 3, b: 4}
n.a=8
console.log(z)  // {a: 3, b: 4}

复制代码

9、Object.defineProperty的做用

今天有看了一篇面试的文章,其中有一题就问到Object.defineProperty的做用,说实话,若是问我,我也答不上来,随即百度找到了解析,而后就顺便添加到这次笔记中,以便之后查看。

语法: Object.defineProperty(obj, prop, descriptor)

参数说明:

obj:必需。目标对象 
prop:必需。需定义或修改的属性的名字
descriptor:必需。目标属性所拥有的特性
复制代码

针对对象到属性,咱们能够给这个属性设置一些特性,属性的值是否能够被重写?好比是否只读?;是否能够被for..inObject.keys()遍历,是否能够删除目标属性或是否能够再次修改属性的特性?

带着上面的问题,咱们来看看Object.defineProperty能给咱们带来哪些神奇的效果(数据描述中的属性都是可选的)!

1. value :属性对应的值,可使任意类型的值,默认为undefined

let obj = {}
//第一种状况:不设置value属性
Object.defineProperty(obj,"newKey",{

});
console.log( obj.newKey );  //undefined

------------------------------

//第二种状况:设置value属性
Object.defineProperty(obj,"newKey",{
    value:"hello"
});
console.log( obj.newKey );  //hello
复制代码

2. writable :属性的值是否能够被重写(默认为false)。设置为true能够被重写;设置为false,不能被重写。

let obj = {}
//第一种状况:writable设置为false,不能重写。
Object.defineProperty(obj,"newKey",{
    value:"hello",
    writable:false
});

//更改newKey的值
obj.newKey = "change value";
console.log( obj.newKey );  //hello
------------------------------------
//第二种状况:writable设置为true,能够重写
Object.defineProperty(obj,"newKey",{
    value:"hello",
    writable:true
});

//更改newKey的值
obj.newKey = "change value";
console.log( obj.newKey );  //change value
复制代码

3. enumerable :此属性是否能够被枚举(使用for...in或Object.keys())。设置为true能够被枚举;设置为false,不能被枚举。(默认为false)。

var obj = {}
//第一种状况:enumerable设置为false,不能被枚举。
Object.defineProperty(obj,"newKey",{
    value:"hello",
    writable:false,
    enumerable:false
});

//枚举对象的属性
for( var attr in obj ){
    console.log( attr );  
}
//第二种状况:enumerable设置为true,能够被枚举。
Object.defineProperty(obj,"newKey",{
    value:"hello",
    writable:false,
    enumerable:true
});

//枚举对象的属性
for( var attr in obj ){
    console.log( attr );  //newKey
}
复制代码

4.configurable :是否能够删除目标属性或是否能够再次修改属性的特性(writable, configurable, enumerable)。设置为true能够被删除或能够从新设置特性;设置为false,不能被能够被删除或不能够从新设置特性。默认为false

这个属性起到两个做用:

目标属性是否可使用delete删除
    
    目标属性是否能够再次设置特性
复制代码
//-----------------测试目标属性是否能被删除------------------------
var obj = {}
//第一种状况:configurable设置为false,不能被删除。
Object.defineProperty(obj,"newKey",{
    value:"hello",
    writable:false,
    enumerable:false,
    configurable:false
});
//删除属性
delete obj.newKey;
console.log( obj.newKey ); //hello

//第二种状况:configurable设置为true,能够被删除。
Object.defineProperty(obj,"newKey",{
    value:"hello",
    writable:false,
    enumerable:false,
    configurable:true
});
//删除属性
delete obj.newKey;
console.log( obj.newKey ); //undefined

//-----------------测试是否能够再次修改属性/特性------------------------
var obj = {}
//第一种状况:configurable设置为false,不能再次修改属性/特性。
Object.defineProperty(obj,"newKey",{
    value:"hello",
    writable:false,
    enumerable:false,
    configurable:false
});

//从新修改属性/特性
Object.defineProperty(obj,"newKey",{
    value:"hello",
    writable:true,
    enumerable:true,
    configurable:true
});
console.log( obj.newKey ); //报错:Uncaught TypeError: Cannot redefine property: newKey

//第二种状况:configurable设置为true,能够再次修改属性/特性。
Object.defineProperty(obj,"newKey",{
    value:"hello",
    writable:false,
    enumerable:false,
    configurable:true
});

//从新修改属性/特性
Object.defineProperty(obj,"newKey",{
    value:"hello",
    writable:true,
    enumerable:true,
    configurable:true
});
console.log( obj.newKey ); //hello
复制代码

除了能够给新定义的属性设置属性/特性,也能够给已有的属性设置属性/特性.

//定义对象的时候添加的属性,是可删除、可重写、可枚举的。
var obj = {
    test:"hello"
}

//改写值
obj.test = 'change value';

console.log( obj.test ); //'change value'

Object.defineProperty(obj,"test",{
    writable:false
})


//再次改写值
obj.test = 'change value again';

console.log( obj.test ); //依然是:'change value'
复制代码

提示:一旦使用Object.defineProperty给对象添加属性,那么若是不设置属性的特性,那么configurableenumerablewritable这些值都为默认的false

var obj = {};
//定义的新属性后,这个属性的特性中configurable,enumerable,writable都为默认的值false
//这就致使了neykey这个是不能重写、不能枚举、不能再次设置特性
//
Object.defineProperty(obj,'newKey',{

});

//设置值
obj.newKey = 'hello';
console.log(obj.newKey);  //undefined

//枚举
for( var attr in obj ){
    console.log(attr);
}
复制代码

参考资料:传送门


做者:晴天de雨滴    
    出处:https://juejin.im/post/5a125827518825293b4fea8a
    版权全部,欢迎保留原文连接进行转载:) 
复制代码

若是你对我对文章感兴趣或者有些建议想说给我听👂,也能够添加一下微信哦!

若是亲感受个人文章还不错的话,能够一下添加关注哦!

gold-cdn.xitu.io/2017/11/19/15fd4be41482278c?w=1000&h=800&f=png&s=204515)

最后:
        祝各位工做顺利!
                        -小菜鸟Christine
复制代码
相关文章
相关标签/搜索