美文网首页
你不知道的JS(上卷)笔记——对象总结

你不知道的JS(上卷)笔记——对象总结

作者: 李牧敲代码 | 来源:发表于2020-02-29 22:47 被阅读0次

本文目录:

  • JS中的所有内置对象
  • 创建对象的方法
  • 深拷贝和浅拷贝(通用方法参考之前的文章,特列方法重新总结下)
  • 属性描述符
  • 不变性
  • Getter和Setter
  • 存在性
  • 遍历

正文

JS中的所有内置对象(内置构造函数)

  1. String
  2. Number
  3. Array
  4. Object
  5. Function
  6. Date
  7. Boolean
  8. Error
  9. RegeXp

创建对象的方法

创建对象的方法我们这里只谈那些实践中可以用的,有缺陷的其实就是下面方法的不完整版

  1. 字面量的形式:
let obj = {
    name: 'obj'
}

  1. 构造函数的形式
function Class1() {
    this.name = 'Class1'
}

let obj = new Class1();

无论像网上其他教程说的那样比如通过new Object或者什么原型模式都是基于构造函数的补充,其本质还是基于构造函数的形式。

function Class1() {
    this.name = 'Class1'
}

let obj = new Class1();
  1. 通过Object.create()
let obj = {
    name: 'obj'
}


let obj2 = Object.create(obj, {
    age: {
        value: 12,
        writable: true,
        configurable: true,
        enumerable: true
    }
})

console.log(obj)
console.log(obj2, obj2.name)
// Object.create()方法创建一个新对象,使用现有的对象(第一个参数)来提供新创建的对象的__proto__。
// Object.create的第二个参数就相当于Object.defineProperty的后面2个参数的集合
  1. 二种方式的联系
        var obj = {}
        Object.create(Object.prototype)
        /*--------------分割线---------------*/
        function Class1() {

        }

        var obj = new Class1();
        Object.create(Class1.prototype)

//以上2种方式两两等价

深拷贝和浅拷贝

参考我的另一篇文章

属性描述符

从ES5开始所有属性都具有了属性描述符,可以通过Object.getOwnPropertyDescriptors获取,通过Object.defineProperty设置

        let obj = {
            name: 'obj'
        }

        Object.defineProperty(obj, 'age', {
            value: 123,
            writable: true,
            configurable: false,
            enumerable: true
        })

        console.log(Object.getOwnPropertyDescriptor(obj, 'name'))//获取单个属性的属性描述符用这个方法
            /*
                {
                    value: 123,//属性的值
                    writable: true,//该属性是否可写,
                    configurable: false,.//该属性的属性描述符是否可配置,只影响configurable和enumerable
                    enumerable: true//该属性是否可枚举,可以参考下面的可枚举性
                }    
            */
        console.log(Object.getOwnPropertyDescriptors(obj))
            /*
                    {
                        age: {
                            value: 123,
                            writable: true,
                            configurable: false,
                            enumerable: true 
                        }           
                        name: {
                            value: 123,
                            writable: true,
                            configurable: false,
                            enumerable: true                     
                        }
                    }
            */

不变性

如果想声明一个对象常量可以通过将writableconfigurable置为false即可。
  • 禁止扩展
let obj = {
    
}

Object.defineProperty(obj, 'age', {
    value: 123,
    writable: true,
    configurable: false,
    enumerable: true
})

Object.preventExtensions(obj)//阻止对象添加新的属性,在严格模式下会报错
obj.b = 321

console.log(obj)//{ age: 123 }      
  • 密封
    无法添加属性,所有属性无法删除,所有属性无法配置,所有属性可以修改值
let obj = {
    name: 'obj'
}

Object.defineProperty(obj, 'age', {
    value: 123,
    writable: true,
    configurable: false,
    enumerable: true
})

Object.seal(obj)
obj.c = 321//无法添加属性
delete obj.name//无法删除属性
Object.defineProperty(obj, 'age', {
    enumerable: false
})//无法配置属性,直接报错

console.log(obj)//{ age: 123 }
console.log(Object.getOwnPropertyDescriptors(obj))
  • 冻结
    在密封的基础上增加不可修改值
let obj = {
    name: 'obj'
}

Object.defineProperty(obj, 'age', {
    value: 123,
    writable: true,
    configurable: false,
    enumerable: true
})

Object.freeze(obj)
obj.c = 321//无法添加属性
delete obj.name//无法删除属性
// Object.defineProperty(obj, 'age', {
//     enumerable: false
// })//无法配置属性,直接报错
obj.name = 666;//无法修改值
console.log(obj)//{ age: 123 }
console.log(Object.getOwnPropertyDescriptors(obj))
  • 深度冻结
    很少用到,可以递归遍历然后通过Objecrt.freeze来是实现。

Getter和Setter

读取一个对象的是实现了JS默认的[[Get]]操作(也就是ES5的Getter)而设置一个对象的属性是实现了默认的[[Put]](也就是ES5的Setter)操作。当然,在ES5之后你可以重写JS内置的GetterSetter方法。
默认的[[Get]]操作会进行如下操作:

  1. 首先会查找是否具有相同的名称的属性,如果找到的话则返回值。
  2. 如果找不到的话则往原型链上找,如果找到的话则返回值。
  3. 如果无论如何都找不到的话则返回undefined(注意区分和变量的区别,在词法作用域中如果不存在某变量,则会报错)。

默认的[[Put]]操作:
该对象自身属性存在的情况:

  1. 会先判断该属性是否是访问描述符(访问器属性),如果是则判断是否有Setter,如果有则调用Setter,没有则调用默认的setter。
  2. 如果不是访问描述符,则判断该属性的writeable是否为true,是则赋值,否则在严格模式下啥都不做,在严格模式下报错。

该对象自身属性不存在的情况:

  1. 简单的说只要原型链上的数据能“改”(包括setter和writable为true的情况),那么就会在自身添加属性,并且会发生属性屏蔽;否则,则啥都不做,严格模式下回报错。

存在性

  1. 检查自身某个属性是否存在用
    Object.hasOwnProperty
  2. 检查自身及其原型链上的某个属性是否存在用
    in
    例子:
let objx = {}

let objy = {a: 12}

objx.__proto__ = objy;

console.log(Object.prototype.hasOwnProperty.call(objx, a))//false
console.log('a' in objx)//true

  1. 检查可枚举属性的方法:
1. Object.keys(obj); //返回obj自身所有可以枚举的属性名组成的数组。
2. propertyIsEnumerable; //检查某个具体属性是否可枚举
  1. 检查所有属性的方法:
1. for.. in
2. getOwnPropertyNames//返回索引名组成的数组
3. every
4. some
5. for ... of //直接返回值

遍历

一个对象可以遍历的的原理是该对象中存在一个【Symbol.iterator】属性,该对象是一个函数,该函数返回一个对象,该对象里面有个名为next的函数,next函数返回一个对象,包含2个属性,一个是value,一个是done.下面是自己实现一个对象的迭代器的例子。

var obj = {
    a: 11,
    b: 22,
    '3': 33
}

Object.defineProperties(obj, {
    [Symbol.iterator]: {
        writable: false,
        enumerable: false,
        configurable: true,
        value: function() {
            let o = this;
            let index = 0;
            let indexArr = Object.keys(o)
            return {
                next: function() {
                    return{
                        value: o[indexArr[index++]],
                        done: (index > indexArr.length)
                    }
                }
                
            }
        }
    }
})


for (let i of obj) {
    console.log(i)
}//本来for in 不能作用于普通对象,但是添加了迭代器了就可以了

相关文章

网友评论

      本文标题:你不知道的JS(上卷)笔记——对象总结

      本文链接:https://www.haomeiwen.com/subject/xubsictx.html