前言
在刚开始学习javascript时候,学习到Object这一章节的时候就特别难懂,到底什么是对象?在一些书本中或者网上的学习资料中,我们都看到过这么一句话:在Javascript中万物皆对象。难道所有一切都是对象吗?难道前面提到过的string,number,boolean也都是对象?可是我们之前说过,这些是基本类型,不是对象。到底哪个是对的?要理解Javascript中的对象,我们还是需要深入语言的底层去一点一点理解。
历史起因
1995年,JavaScript诞生之年,Netscape公司(JavaScript的设计者)与Sun公司(Java语言的发明者和所有者)合作开发一种可以嵌入网页的脚本语言,将JavaScript的数据结构借鉴Java而设计,包括将值分成原始值和对象两大类。
Java中一切皆对象,但基本类型却不是对象,为了解决这个问题,Java让每个基本类型都对应了一个包装器类型。 包装器类型将基本类型包装起来,添加了属性和方法,包装器类型即为对象,所以可以这么说Java中的一切都可以充当对象,不会说的那么绝对。
因此JavaScript借鉴了Java数据结构的也同样在基本类型中各对应了一个包装器类型,JavaScript中的一切都可以充当对象。
一、Javascript中的数据结构
目前,javascript中一共有7种基本数据类型:
- Number:用于表示整数和浮点数
- BigInt:用于表示任意大小的整数
- String:用于表示文本数据或字符序列
- Boolean:用于表示逻辑值
- Symbol:表示唯一的、不可变的原始值
- Null:表示一个空值或"无"的值
引用类型(对象):
- Object,Array,Function
- 单体内置对象:Global,Math
- es6新增:Map,Set,WeakMap,WeakSet
- 基本包装类型:Boolean,Number,String,Symbol,BigInt
- 其他内置函数:RegExp,Date,Error
二、包装类型
先看下下面的例子:
js
var str = 'hello javascript';
console.log(str.length) // 15
上面的例子中,声明了一个基本类型变量str,它既然是一个基本类型,又为什么会有方法呢?这里就是javascript自动包装了,将基本类型通过对应的包装类型,包装成对象,大概经过以下3步:
- 创建一个String实例;
js
var str1 = new String('hello javascript')
- 调用实例的方法;
js
console.log(str1.length)
- 销毁实例;
js
str1 = null
三、再理解一切皆对象
准确的说,不能说全部都是对象,但也基本不差;基本数据类型都有对应的包装对象,在使用时将其包装为对象。但这里除null和undefined之外。所以可以说基本都是对象。
typeof null返回Object其实是语言自身的一个bug;不同的对象在底层都表示为二进制,在javascript中二进制前3为都为0的话会被判断为object类型;而null的二进制全是0,自然前3位也是0,所以执行tyoeof返回object。
四、基本类型和引用类型的区别
基本类型:
由于基本类型存储的值比较简单,占用内存相对较小,所以基本类型被存放在栈内存中;将一个基本类型变量赋值给另外一个变量时候,相当于在栈内存重新分配了一个独立空间给新的变量存放基本类型值。
引用类型:
引用类型的值理论上可以无限大,对象可以嵌套;值越大,就越占内存;如果将一个特别的的值随意复制,那么将是一个灾难的设计;所以对象被称为引用类型,是因为值被存放在堆内存中,变量只保存指向对象的引用路径;将一个对象变量赋值给另一个变量时候,等于复制了一个引用给新对象,但是引用共同指向一个对象。
五、创建对象
- 对象直接量
js
var obj = {}
- new
js
var obj = new Object()
- Object.create() 创建没有原型的对象,真的空对象。
js
var obj = Object.create(null)
console.log(obj._proro_ === undefined) // true
六、对象继承的核心
javascript对象可以从一个称为原型 的对象里继承属性。这种原型继承是javascript的核心。
js
var hello = {name: 'hello'}
console.log(hello)
看上面的打印结果,会发现hello对象除了name属性,还多了一个[[Prototype]],并且这个对象包含很多自身属性。
这是因为在创建对象的过程中,底层已经做了隐式继承的操作,也可以称为原型继承。[[Prototype]]正是继承Object的原型(Object.prototype)
注意理解: 实例hello是继承Object.prototype而不是Object
js
hello.__proto__ === Object.prototype // true
上面图片中,多出来的[[prototype]]属性对象,正是Object.prototype对象;hello实例通过原型对象_proto_获得继承。
最后
前面分了5个部分对javascript中的对象进行了理解说明,如有不对之处欢迎评论区交流学习。