在JavaScript的世界里,有一句广为流传的箴言:“万物皆对象”。初学JS时,我们常常对此深信不疑——毕竟连数组、函数甚至是函数本身的属性,似乎都能挂载上各种自定义的键值对。然而,当你写下 toString () 报错时,这个看似绝对的真理便开始摇摇欲坠。JavaScript中的“对象”到底是什么?它仅仅是一堆键值对的集合吗?
在聊万物皆对象前我们先要了解js的2种类型
1.原始类型:number、string、boolean、null、undefined、symbol、bigint
2.引用类型:object、function、array、date
一、创建对象的方式
1.字面量
const obj = { // 对象字面量
name:'猪猪侠'
}
let hello = 'world'
obj[hello] = 123 // 往对象里面增加变量属性用[变量名]
delete obj[hello] // 删除对象属性
2.构造函数 (new Object())
const obj = new Object() // 构造函数创建对象
obj.name = '猪猪侠'
console.log(obj);
3.new 一个构造函数
function Person() {
}
// Person()
const obj = new Person()
函数有二义性:可以普通调用,也可以 new 调用
二、new 的工作原理
function Car(color) {
// var this = {}
this.name = 'bmw'
this.height = 1400
this.long = 4900
this.wide = 1700
this.color = color
// this.__proto__ = Car.prototype
// return this
}
const aCar = new Car('pink') // 实列对象
const bCar = new Car('blue')
bCar.name = '劳斯莱斯'
console.log(aCar);
console.log(bCar);
工作原理:
1.new 会往函数内凭空创建一个对象(this = {} )
2.执行函数中的代码
3.让这个对象的原型 等于 函数的原型 ( this.__ proto __ = Xxx.prototype )
4.retun 这个对象(this = {} )
原型:
1.所有的 函数都天生有一个属性:prototype
2.对象 天生拥有一个属性:_ proto _
var str = 'abc' // const strObj = new String('abc')
str.length = 4 // strObj.length = 4 delete strObj.length
console.log(str.length);
上面这个代码输出结果为3,我们要如何将输出结果改为4呢?这就需要我们在原型上面进行更改了即以下方式
String.prototype.len = 4
var str = 'abc'
console.log(str.len)
三、包装类
讲这个之前我们要先了解2个规则:
1.原始类型是不能添加属性和方法的
2.V8 在对象中查找属性,如果找不到,一定会去它原型上找
const str = 'hello' // 字符串字面量 const str = new String('hello')
str.name = '猪猪侠' // str.name = '猪猪侠' 不会报错,但是没有效果
// delete str.name 删除属性
// str.[[PrimitiveValue]]
console.log(str);
console.log(str.name); // undefined
工作过程:
1.当用户创建一个字面量, V8 会默认执行成 new Xxx()
2.因为原始类型不能增加属性和方法,所以 V8 在 new 出这个实列对象后,立即会做一个拆箱操作
3.例:str.length length 是 String 函数原型上的属性,并不是给字符串增加的属性
四、总结
总而言之,JavaScript中的对象绝非简单的“键值对集合”,而是融合了动态属性描述、原型链继承与元编程代理的精巧机制;当我们拨开“万物皆对象”的表象迷思,深入V8隐藏类的内存布局与属性描述符的精细管控,并理顺__proto__构建的寻址链路时,便真正掌握了这门语言的核心运转逻辑,从而能在日常开发中写出契合引擎优化、避开深层陷阱的高质量代码。