我不知道是js-对象

188 阅读5分钟
原文链接: qxfuture.com

对象

对象可以通过两种形式定义:声明(文字)形式和构造形式。
对象的文字语法大概是这样:

var myObj = { 
    key: "aaa'
};

构造形式大概是这样:

var myObj = new Object(); 
myObj.key = "aaa";

基本类型

• string
• number
• boolean
• null
• undefined
• object
简单基本类型(string、boolean、number、null 和 undefined)本身并不是对象
实际上,null 本身是基本类型
原理是这样的,不同的对象在底层都表示为二进制,在 JavaScript 中二进制前三位都为 0 的话会被判 断为 object 类型,null 的二进制表示是全 0,自然前三位也是 0,所以执行 typeof 时会返回“object”。

内置对象

• String
• Number
• Boolean
• Object
• Function
• Array
• Date
• RegExp
• Error

操作对象的一些方法

Object.assign()

ES6 定义了 Object.assign(..) 方法来实现浅复制。Object.assign(..) 方法的第一个参数是目标对象,之后还可以跟一个或多个源对象。它会遍历一个或多个源对象的所有可枚举(enumerable) 的自有键并把它们复制到目标对象,最后返回目标对象

Object.getOwnPropertyDescriptor()

ES5开始,所有的属性都具备了属性描述符

var myObject = { a:2
};
Object.getOwnPropertyDescriptor( myObject, "a" );
// {
// value: 2,
// writable: true,// 可写
// enumerable: true,//可枚举
// configurable: true //可配置
// }

Object.defineProperty()

给对象添加一个新属性或者修改一个已有属性(如果它是 configurable)并对特性进行设置

var myObject = {};
Object.defineProperty( myObject, "a", {
    value: 2,
    writable: true, 
    configurable: true, 
    enumerable: true
});
myObject.a; // 2

如果把上面的属性 configurable: false 然后调用 delete myObject.a; 是删除失败的,依然可以获取到 myObject.a,原因就是因为configurable: false

Object.preventExtensions()

如果你想禁止一个对象添加新属性并且保留已有属性,可以使用 Object.prevent Extensions(..)

var myObject = { 
    a:2
};
Object.preventExtensions( myObject );
myObject.b = 3;
myObject.b; // undefined

在非严格模式下,创建属性 b 会静默失败。在严格模式下,将会抛出 TypeError 错误。

Object.seal()

Object.seal(..) 会创建一个“密封”的对象,这个方法实际上会在一个现有对象上调用 Object.preventExtensions(..)并把所有现有属性标记为 configurable:false,
就是不能调用Object.defineProperty()
所以,密封之后不仅不能添加新属性,也不能重新配置或者删除任何现有属性(虽然可以 修改属性的值)。

Object.freeze()

Object.freeze(..) 会创建一个冻结对象,这个方法实际上会在一个现有对象上调用 Object.seal(..) 并把所有“数据访问”属性标记为 writable:false,这样就无法修改它们的值。

hasOwnProperty() 和 in

hasOwnProperty()这个是对象实例的方法

var myObject = { 
    a:2
};

myObject.hasOwnProperty( "a" );// true
("a" in myObject); // true

in操作符会检查属性是否在对象及其[[Prototype]]原型链中。hasOwnProperty(..)只会检查属性是否在myObject对象中,不会检查[[Prototype]]链。

propertyIsEnumerable()

propertyIsEnumerable()这个是对象实例的方法
会检查给定的属性名是否直接存在于对象中(而不是在原型链 上)并且满足 enumerable:true

var myObject = { 
    a:2
};
myObject.propertyIsEnumerable( "a" ); // true

Object.keys()

会返回一个数组,包含所有可枚举属性,只会查找对象直接包含的属性,不会检查[[Prototype]]链。

var myObject = { 
    a:2
};
Object.keys( myObject ); // ["a"]

Object.getOwnPropertyNames()

会返回一个数组,包含所有属性,无论它们是否可枚举,只会查找对象直接包含的属性,不会检查[[Prototype]]链。

var myObject = { 
    a:2
};
Object.defineProperty(
    myObject,
    "b",
    // 让 b 不可枚举
    { enumerable: false, value: 3 }
);
Object.getOwnPropertyNames( myObject ); // ["a","b"]

[[Put]]

给对象的属性赋值会触发 [[Put]] 来设置或者创建这个属性。但是实际情况并不完全是这样。
[[Put]] 被触发时有两种情况对象已存在这个属性,和不存在这个属性
如果已经存在这个属性,[[Put]] 算法大致会检查下面这些内容。

  1. 属性是否是访问描述符?如果是并且存在setter就调用setter。
  2. 属性的数据描述符中writable是否是false?如果是,在非严格模式下静默失败,在严格模式下抛出 TypeError 异常。
  3. 如果都不是,将该值设置为属性的值。

Getter和Setter

getter 是一个隐藏函数,会在获取属性值时调用。setter 也是一个隐藏 函数,会在设置属性值时调用。
给对象的一个属性定义 getter、setter 或者两者都有时,这个属性会被定义为“访问描述 符”(和“数据描述符”相对)。

var myObject = {
// 给 a 定义一个 getter 
get a() {
    return this._a_; 
},
// 给 a 定义一个 setter 
set a(val) {
    this._a_ = 2; }
};

Object.defineProperty( 
    myObject, // 目标对象 
    "b", // 属性名
    {   // 描述符
        // 给 b 设置一个 getter
        get: function(){ return 2 },
        // 确保 b 会出现在对象的属性列表中
        enumerable: true
    })

[[Prototype]]

JavaScript 中的对象有一个特殊的 [[Prototype]] 内置属性,其实就是对于其他对象的引用。几乎所有的对象在创建时 [[Prototype]] 属性都会被赋予一个非空的值(对象的 [[Prototype]] 链接可以为空)。
[[Prototype]] 引用有什么用呢?当你试图引用对象的属性时会触发,[[Get]] 操作,检查对象本身是 否有这个属性,如果有的话就使用它。如果没有,就需要使用对象的[[Prototype]]

属性设置和屏蔽

分析myObject.foo = "bar";会有怎样的过程,
foo不在myObject中而是存在于原型链上层时 myObject.foo = "bar" 会出现的三种情况。

  1. 如果在[[Prototype]]链上层存在名为foo的普通数据访问属性并且没有被标记为只读(writable:false),那就会直接在 myObject 中添加一个名为 foo 的新 属性,它是屏蔽属性。
  2. 如果在[[Prototype]]链上层存在foo,但是它被标记为只读(writable:false),那么 无法修改已有属性或者在 myObject 上创建屏蔽属性。如果运行在严格模式下,代码会 抛出一个错误。否则,这条赋值语句会被忽略。总之,不会发生屏蔽。
  3. 如果在[[Prototype]]链上层存在foo并且它是一个setter,那就一定会 调用这个setterfoo不会被添加到(或者说屏蔽于)myObject,也不会重新定义foo这个 setter

对象和类之间原型链

prototype prototype

参考文献

你不知道的js