引言:万物皆对象
在JavaScript中,几乎"万物皆对象"。无论是数组、函数还是基本类型值,都可以被视为对象进行处理。这种设计理念使得JavaScript具有极高的灵活性和动态性。
一、对象的创建方式
JavaScript提供了多种创建对象的方式:
1. 对象字面量
最简洁直观的对象创建方式:
ini
const obj = {
name: "pp",
age: 19
};
// 动态添加/修改属性
obj.sex = "boy";
obj.age = 15;
// 删除属性
delete obj.sex;
console.log(obj["age"]); // 15
2. new Object()构造函数
使用内置的Object构造函数:
javascript
var obj2 = new Object();
console.log(obj2); // {}
3. 自定义构造函数
(批量创建对象)
ini
function Car(color) {
this.name = "666";
this.color = color;
}
var car1 = new Car("red");
var car2 = new Car("orange");
car1.name = "999";
console.log(car1); // {name: "999", color: "red"}
console.log(car2); // {name: "666", color: "orange"}
二、构造函数与new操作符
当一个函数被new
调用时,它成为构造函数,v8引擎会执行以下步骤:
文字描述就是
1.创建了一个 this 对象
2.执行构造函数中的代码,并给 this 对象添加属性和方法
3.返回 this 对象
具体代码实现:
ini
function Person(name, age, sex) {
// 1. 隐式创建 this = {}
this.name = name;
this.age = age;
// 3. 隐式返回 this
}
var person = new Person("pp", 12);
console.log(person); // { name: "pp",age: 12}
所以person这里接收了对象,对吧
手动模拟new操作符的过程:
ini
function Person(name, age, sex) {
var _this = {};//显式的创建一个对象
_this.age = age;
_this.name = name;
_this.sex = sex;
return _this;//显式的返回一个对象
}
var person = new Person("pp", 12);
console.log(person); // { name: "pp",age: 12}
三、包装类:原始值的对象包装
- 用户定义的字面量,会被包装成对象(比如:new Number())
- 一个包装类的实例对象,在参与运算时,会被自动拆箱成原始类型(比如:number)友友们
- 因为 js 是弱语言,所以只有在赋值语句执行时才会判断值的类型,当值被判断为原始类型时,就会自动的将包装对象上调价的属性移除
数据类型忘了的友友们可以看我之前的文章哦
JavaScript为每个原始类型提供了对应的包装对象:
原始类型 | 包装对象 | 示例 |
---|---|---|
number | Number | new Number(42) |
string | String | new String("hello") |
boolean | Boolean | new Boolean(true) |
symbol | Symbol | Symbol("desc") |
bigint | BigInt | BigInt(9007199254740991) |
包装类的特性
ini
//铁律:原始类型一定不能添加属性和方法,属性和方法是对象独有的
var num = 123;
num.a = "aaa";
console.log(num.a); // undefined

我们定义了原始数据类型,但它是不是默认提供了包装对象 Number对吧,var num = 123;
这里执行的时候会默认执行成 var num =new Number(123)
那它算不算是对象呢?
它算对象,可这里打印时却并没有打印出我们放在对象的属性,这里执行时也没有报错,只是结果为undefined。为什么呢?结果为undefined说明我们们打印的是空对象,
可为什么是空对象呢?
这就不得不提v8执行机制了,这里v8在执行var num = 123;
时确实会将它默认执行成 var num =new Number(123)
这样,但是 这里我们原先想创建的是原始数据类型对吧,v8在这里会判断到我们想要创建的是原始数据类型,这时铁律生效,原始数据类型怎么能有属性和方法呢,v8引擎就会在添加对象属性时,将属性删除掉,所以结果为undefined,想必你一定明白了,那我们来看下面这段代码:
ini
// 显式创建包装对象
var num1 = new Number(123);
num1.a = "aaa";
console.log(num1 + 1); //124
console.log(num1.a);

这里我们同样创建原始数据 可我们是通过构造函数的方式来创建num1的,
那我们还能算是创建了一个原始数据类型吗?
这里的num1其实是对像,既然是对象那为什么能打印结果124呢? 这是因为当进行四则运算时,v8会自动把new时给的值读取出来进行运算
那为什么v8是怎么判断我们想要创建的是什么数据是什么数据类型呢? 是通过typeof来判断的
四、数据类型检测
1. typeof 操作符
js
console.log(typeof "hello"); // "string"
console.log(typeof 123); // "number"
console.log(typeof true); // "boolean"
console.log(typeof undefined); // "undefined"
console.log(typeof Symbol()); // "symbol"
console.log(typeof 123n); // "bigint"
console.log(typeof null); // "object" (历史遗留问题)
console.log(typeof {}); // "object"
console.log(typeof []); // "object"
console.log(typeof function(){});// "function"
v8在我们创建数据时,会自动通过typeof来判断我们想要创建的是原始数据类型还是引用数据类型,但是不能判断具体数据类型
js
var str = "pp"; //new String('hello')
str.length = 3;
console.log(str.length);

为什么原始数据类型有属性,我们只需要记住这里的length不是str的属性而是继承下来的
面试官爱问的:下面输出结果是什么
js
var arr = [1, 2, 3, 4, 5]; //数组也是对象,特殊的对象
arr.length = 2;
console.log(arr);
var str='abcd'
str2.length=2
console.log(str2.length);

是继承的属性,而本身没有,所以这里是添加一个length属性,但是v8判断是属性,v8又会删除掉该属性, 而这打印出来的是继承下来的属性,不是本身的
null为什么是object呢?
其实是因为typeof是通过判断转换为二进制数后的数据的0个数来判断是引用类型还是原始数据类型
1.typeof 可以准确的判断除了 null 以外的所有原始类型 第一步会将拿到的转化为二进制 对象类型转化为二进制的前三位必为 0 ,所以前三位为 0 的话就是引用数据类型,前三不为 0 的话就是原始数据类型,而null在二进制中为一串0,因此null为object,并且使用typeof不能准确判断引用数据类型到底是哪种具体类型,那有没有办法呢,当然有,在下篇文章会讲到,笔者还在创作中
2. 更精确的类型检测方法?
下篇文章会讲到
五、总结
JavaScript的对象系统是其核心特性,理解对象创建、构造函数和类型检测对于掌握JavaScript至关重要。
实践建议:
- 优先使用对象字面量语法创建对象
- 构造函数命名采用大驼峰式(PascalCase)
- 使用
typeof
检测原始类型,但要注意null
的陷阱
如有错误欢迎指正,欢迎各位友友评论点赞!