对象
在 JavaScript 中,对象是一种复杂的数据类型 ,用于存储具有相关属性和方法的数据结构 。对象是基于键值对 的集合,其中键是字符串 (或者符号 Symbol),值可以是任何数据类型,包括函数,这些函数被称为对象的方法。
对象中属性的增加
我们先来看如下代码;
可以看到,我们用mrPeng.like = '章若楠'
往对象mrPeng
中添加了一个key
为like
,值为 '章若楠' 的属性;
但如果我们要是写成这样呢?
我们先定义了一个字符串abc
为like
,再通过mrPeng.abc = '刘亦菲'
往对象中添加属性,此时添加属性的key
是什么呢?
可以看到,新增属性的key
就为abc
;并没有引用定义的字符串abc
的值。这是因为在对象中,key只能是字符串类型 ;所以用.abc
添加属性的方法就把abc
当作字符串 传给了key
。
那可不可以把abc
当成变量传给key
呢?可以,只不过要换一种方式;
mrPeng[abc] = '刘亦菲'
,这是js中的一种语法,也可以往对象之中添加属性,[]
允许使用变量作为属性名称。
与传统方法不同的是,它把abc
当作变量并找到它的值传给了key
。
对象中属性的删除
js中提供了delete
的语法,用于删除对象中的属性;
可以看到,sex
属性就被删除了。
对象的创建
创建对象字面量
在js中,最简单的创建对象的方法,那就是直接创建一个对象字面量;再给它添加上需要的属性和方法。
csharp
// 创建对象字面量
var obj = {}
new Object()
除了对象字面量之外,我们还可以通过 Object()
构造方法去实例化一个空对象;
new XXX() 自定义的构造函数
再就是,我们可以自定义构造函数 ,用new
方式去实例化一个对象:
实例化出来的对象如下:
new
在上篇文章中,我们已经介绍过new
的过程了;在这里,我们还可以用另外一种更加通俗的方式来理解new
的过程;
kotlin
function Car(color) {
this.name = 'su7'
this.height = 1400
this.lang = 5000
this.weight = 1000
this.color = color
}
// new 过程
// 先创建this空对象
var this = {}
// 执行函数中的代码,往this对象中添加属性
this.name = 'su7'
this.height = 1400
this.lang = 5000
this.weight = 1000
this.color = color
// 返回this对象
return this
由于this
指向的就是实例化的对象 ,故而我们可以直接把this
当成实例化的对象;再向其中添加属性。
不通过new 实例对象
如果我们不使用new
方法去实例化对象,那我们可以把new
的过程直接写在构造函数里面;
在上面的这种形式中,也能够实例化一个对象。
包装类
在JavaScript中,包装类(Wrapper Classes)是一组特殊的构造函数 ,它们能够将基本数据类型(primitive types)封装成对象 。这样做的主要目的是为了让基本类型的值能够拥有属性和方法 。JavaScript提供了三个内置的包装类,分别对应三种基本数据类型:Number
, String
, 和 Boolean
。
原始数据类型
在js中,原始数据类型 (也称为基本数据类型或简单数据类型)是不可变的数据类型;主要分为以下几种:Number,String,Boolean,undefined,null,Symbol 和 BigInt
;我们知道,原始值身上是不能有属性和方法的,属性和方法只有对象才能拥有。但是看着如下一段代码,你陷入了沉思;
str
明明是字符串类型,那它怎么还能调用方法呢?实则不然,在原始数据类型中,Number,String 和 Boolean
都有内置的构造函数。
原始类型的内置方法
在js中,一切皆可看作对象 ;其实原始数据类型也是由它们自身内置的构造函数new
出来的对象,如下图;
用上述方式构造出来的对象就是包装对象 ;这些包装对象具有与它们所封装的基本类型相对应的属性和方法 ,比如,字符串string
能够调用.length
方法去获取字符串的长度。
原始值上挂载属性
因为Number
原始值我们可以把它看成是一个包装对象 ,当我们往原始值上挂载一个属性时,会发生什么呢?
在上面中,我们就往num
上面挂载了一个len
属性为3,但是打印的时候,输出了undefined
;
这是因为在JavaScript中,当你尝试在一个原始值上添加属性时,实际上是在创建并操作一个临时的包装对象 。但是,这种添加的属性不会持久存在,一旦操作完成,这个临时的包装对象就会被销毁,所以你添加的属性似乎"消失"了。这是因为原始值本身不支持属性的挂载。
valueOf 返回对象的"原始值"
在JavaScript中,valueOf
方法是一个内置的方法,几乎所有的对象都有这个方法。valueOf
的主要作用是返回对象的"原始值" 。这个方法通常用于将对象转换为其代表的原始数据类型 ,尤其是当对象被设计为封装某种基本数据类型的时候。
ini
var str = 'abc' // new String('abc')
str += 1 // str = 'abc1'
var test = typeof(str) // 'string'
if (test.length === 6) {
test.sign = 'typeOf的返回结果可能是String'
// new String(test).sign = 'xxxx'
// valueOf(test) 判断是否为原始值类型
// delete test.sign
}
console.log(test.sign); // new String(test).sign undefined
每当你往原始值身上挂载属性时,包装对象的valueOf
内置方法就会返回它的原始值;如果是原始类型,v8引擎会把原始值身上添加的属性给delete
移除掉;因为在v8看来,原始值是不能拥有属性和方法的。
小结
在原始值对象中,当v8执行到包装类时,会通过valueOf
方法试探该包装类是不是原始值 ,如果是,则秉承原始值不用具有属性和方法的 这一规则,再移除掉给包装类添加的属性。