JS原生引用类型解析1-Object类型

(注1:如果有问题欢迎留言探讨,一起学习!转载请注明出处,喜欢可以点个赞哦!) (注2:更多内容请查看我的目录。)

1. 简介

Object是ECMAScript中使用最多的一个类型,所有引用类型默认都继承Object,这种既成通过原型链实现,所有对象从Object.prototype继承方法和属性,尽管它们可能被覆盖。

例如,其他构造函数的原型将覆盖constructor属性并提供自己的toString()方法。Object原型对象的更改将传播到所有对象,除非受到这些更改的属性和方法将沿原型链进一步覆盖。

所以我们需要对Object的内置属性和方法有一个清晰的认识。

2. Object构造函数的使用

前面我们讲过创建对象的各种方法。其中,Object构造函数为给定值创建一个对象包装器。

如果给定值是null或undefined,将会创建并返回一个空对象。否则,将返回一个与给定值对应类型的对象。

当以非构造函数形式被调用时,Object 等同于 new Object()。

3. Object构造函数的属性与方法

我们用Object.getOwnPropertyNames()方法获取Object构造函数的所有属性与方法。

Object.getOwnPropertyNames(Object);
// (23) ["length", "name", "prototype", "assign", "getOwnPropertyDescriptor", "getOwnPropertyDescriptors", "getOwnPropertyNames", "getOwnPropertySymbols", "is", "preventExtensions", "seal", "create", "defineProperties", "defineProperty", "freeze", "getPrototypeOf", "setPrototypeOf", "isExtensible", "isFrozen", "isSealed", "keys", "entries", "values"]

发现一共有23个属性和方法。

3.1 Object构造函数的属性

Object.length 长度为1

Object.name 名称为"Object"

Object.prototype 指向Object构造函数的原型,可以为所有 Object 类型的对象添加属性。

3.2 Object构造函数的方法

Object.assign() 用于将所有可枚举属性的值从一个或多个源对象复制到目标对象,复制过程对已存在的属性会进行覆盖。它将返回目标对象。

var obj = {
    a: 0,
    d: 6
}
var obj1 = {
    a: 1,
    b: 2
}
Object.defineProperty(obj1, 'c', {
    value: 3,
    enumerable: false
});
var obj2 = Object.assign(obj, obj1);
console.log(obj);  // {a: 1, d: 6, b: 2}
console.log(obj2); // {a: 1, d: 6, b: 2}

Object.create() 使用指定的原型对象及其属性去创建一个新的对象。(具体可参考JS入门难点解析10-创建对象

Object.defineProperty() 直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回这个对象。(具体可参考JS入门难点解析13-属性描述符,数据属性和访问器属性

Object.defineProperties() 直接在一个对象上定义多个新属性,或者修改一个对象的现有属性,并返回这个对象。

Object.entries() 该方法接收一个对象为参数,返回该对象自身可枚举属性的键值对数组,其排列与使用for...in...循环循环遍历该对象时返回的顺序一致(区别在于 for-in 循环也枚举原型链中的属性)。(具体可参考JS常用方法整理-遍历对象

Object.freeze() 可以冻结一个对象,冻结指的是不能向这个对象添加新的属性,不能修改其已有属性的值,不能删除已有属性,以及不能修改该对象已有属性的可枚举性、可配置性、可写性。也就是说,这个对象永远是不可变的。该方法返回被冻结的对象。(具体可参考JS入门难点解析13-属性描述符,数据属性和访问器属性

Object.getOwnPropertyDescriptor() 返回指定对象上一个自有属性对应的属性描述符。(自有属性指的是直接赋予该对象的属性,不需要从原型链上进行查找的属性)

Object.getOwnPropertyNames() 返回一个由指定对象的所有自身属性的属性名(包括不可枚举属性但不包括Symbol值作为名称的属性)组成的数组。(具体可参考JS常用方法整理-遍历对象

Object.getOwnPropertySymbols() 回一个给定对象自身的所有 Symbol 属性的数组。

Object.getPrototypeOf() 返回指定对象的原型(内部[[Prototype]]属性的值)。

Object.is() 判断两个值是否是相同的值。如果下列任何一项成立,则两个值相同:

  • 两个值都是 undefined
  • 两个值都是 null
  • 两个值都是 true 或者都是 false
  • 两个值是由相同个数的字符按照相同的顺序组成的字符串
  • 两个值指向同一个对象
  • 两个值都是数字并且
    • 都是正零 +0
    • 都是负零 -0
    • 都是 NaN
    • 都是除零和NaN外的其它同一个数字

这种相等性判断逻辑和传统的 == 运算符所用的不同,== 运算符会对它两边的操作数做隐式类型转换(如果它们类型不同),然后才进行相等性比较,(所以才会有类似 "" == false 为 true 的现象),但 Object.is 不会做这种类型转换。

这与 === 运算符也不一样。=== 运算符(和 == 运算符)将数字值-0和+0视为相等,并认为Number.NaN不等于NaN

Object.is('foo', 'foo');     // true
Object.is(window, window);   // true

Object.is('foo', 'bar');     // false
Object.is([], []);           // false

var test = { a: 1 };
Object.is(test, test);       // true

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

// 特例
Object.is(0, -0);            // false
Object.is(-0, -0);           // true
Object.is(NaN, 0/0);         // true

Object.isExtensible() 判断一个对象是否是可扩展的(是否可以在它上面添加新的属性)。

Object.isFrozen() 判断一个对象是否是被冻结的。

Object.isSealed() 判断一个对象是否是被密封的。

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

Object.preventExtensions() 让一个对象变的不可扩展,也就是永远不能再添加新的属性。

Object.seal() 让一个对象密封,并返回被密封后的对象。密封对象将会阻止向对象添加新的属性,并且会将所有已有属性的可配置性(configurable)置为不可配置(false),即不可修改属性的描述或删除属性。但是可写性描述(writable)为可写(true)的属性的值仍然可以被修改。

Object.setPrototypeOf() 设置一个指定的对象的原型 ( 即, 内部[[Prototype]]属性)到另一个对象或null 注意:Object.setPrototypeOf()是ECMAScript 6最新草案中的方法,相对于Object.prototype._proto_,它被认为是修改对象原型更合适的方法。但是,如果你关心性能,你应该避免设置一个对象的[[Prototype]]。相反,你应该使用 Object.create()来创建带有你想要的[[Prototype]]的新对象。

Object.values() 返回一个给定对象自己的所有可枚举属性值的数组,值的顺序与使用for-in循环的顺序相同 ( 区别在于 for-in 循环枚举原型链中的属性 )。

4. Object原型对象的属性与方法

我们用Object.getOwnPropertyNames()方法获取Object原型对象的所有属性与方法。

Object.getOwnPropertyNames(Object.prototype);
// (12) ["constructor", "__defineGetter__", "__defineSetter__", "hasOwnProperty", "__lookupGetter__", "__lookupSetter__", "isPrototypeOf", "propertyIsEnumerable", "toString", "valueOf", "__proto__", "toLocaleString"]

发现一共有12个属性和方法。

4.1 Object原型对象的属性

Object.prototype.constructor 指向构造函数Object

Object.prototype._proto_ 对于Object.prototype,其值为null,以此避免无限循环。构造函数新建实例对象时,在实例对象调用会指向实例对象的原型对象。该特性为非标准特性,尽量不要使用。

4.2 Object原型对象的方法

Object.prototype.hasOwnProperty() 该方法会返回一个布尔值,指示对象自身属性(非原型链继承)中是否具有指定的属性。

Object.prototype.isPrototypeOf() 该方法返回一个布尔值,表示指定的对象是否在本对象的原型链中。

Object.prototype.PropertyIsEnumerable() 该方法返回一个布尔值,判断指定属性是否可枚举。

Object.prototype.toString() 如果此方法在自定义对象中未被覆盖,toString() 返回 "[object type]",其中type是对象的类型。对于Object.prototype.toString(),其值为"[object Object]"。

Object.prototype.toLocalString() 返回一个该对象的字符串表示。此方法被用于派生对象为了特定语言环境的目的(locale-specific purposes)而重载使用。绝大多数情况下和Object.prototype.toString()一样。

Object.prototype.valueOf() 返回值为该对象的原始值。

5. Object实例对象的属性与方法

我们用Object.getOwnPropertyNames()方法获取Object实例对象的所有属性与方法。

var obj = new Object({a:1,b:2});
Object.getOwnPropertyNames(obj);  // ["a", "b"]

传入属性的key值即为其属性。但是有一点要注意的是,此时可以使用obj._proto指向其原型对象,这个_proto属性按照《JAvaScript高级程序设计》一书和我们前面的分析,按道理应该是实例属性,但这里却并不是(或者是虽然是,但是无法被Object.getOwnPropertyNames()方法列出,如果这样的话,也说得通),不知道底层具体是如何来实现的,如果是共享自Object原型,为什么每一个实例的值都是不同的。(如果有懂这块的同学,还请不吝赐教。)

参考

MDN-Object

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏blackheart的专栏

[C#2] 1-泛型

1. 泛型概述 泛型是一种类型的多态;比如当我们写一个栈或者队列的时候,需要指定其数据类型,int一份代码,string一份代码,object的一份代码, 这些...

22810
来自专栏用户2442861的专栏

JS面向对象的程序设计

http://www.cnblogs.com/gaojun/p/3386552.html

791
来自专栏日常学python

一文解开可迭代对象和迭代器的神秘面纱

可迭代对象和迭代器是两种不同的数据类型,它们都在我们的编程中时常可以遇到。当然他们之间也有很大的关联,接下来就让我们把它们搞定。

1124
来自专栏Java技术分享

反射技术概述

主要是指程序可以访问、检测和修改它本身状态或行为的一种能力

20310
来自专栏微信公众号:Java团长

Java基础之反射(非常重要)

(使用的前提条件:必须先得到代表的字节码的Class,Class类用于表示.class文件(字节码))

963
来自专栏陈纪庚

javascript冷知识

  如果放在数值前的话,对数值不会产生任何影响,不过放在其他的数据类型前面的话,就等于调用number()将他转为数字,布尔值false被转为0,ture被转为...

1123
来自专栏Coco的专栏

一道面试题引发的对javascript类型转换的思考

对于一个好奇的切图仔来说,忍不住动手尝试了一下,看到题目首先想到的是会用到高阶函数以及 Array.prototype.reduce()。

2864
来自专栏专注 Java 基础分享

java基础之继承(一)

虽然说java中的面向对象的概念不多,但是具体的细节还是值得大家学习研究,java中的继承实际上就是子类拥有父类所有的内容(除私有信息外),并对其进行扩展。下面...

2018
来自专栏前端知识分享

第172天:面向对象基本知识点

                     2 .构造函数内部会创建一个新的对象,即f的实例

903
来自专栏互扯程序

大牛:你真的懂反射吗?

现在是资源共享的时代,同样也是知识分享的时代,如果你觉得本文能学到知识,请把知识与别人分享。

1363

扫码关注云+社区

领取腾讯云代金券