JavaScript对象深度解析:从创建到类型判断 (上)

引言:万物皆对象

在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至关重要。

实践建议:

  1. 优先使用对象字面量语法创建对象
  2. 构造函数命名采用大驼峰式(PascalCase)
  3. 使用typeof检测原始类型,但要注意null的陷阱

如有错误欢迎指正,欢迎各位友友评论点赞!

相关推荐
brzhang5 分钟前
Android 16 卫星连接 API 来了,带你写出「永不失联」的应用
前端·后端·架构
John_ToDebug19 分钟前
Chrome 浏览器前端与客户端双向通信实战
前端·c++·chrome
要加油哦~23 分钟前
CSS | transition 和 transform的用处和区别
前端·css
小鱼人爱编程34 分钟前
现代大前端是如何编码的?
android·前端·flutter
神仙别闹37 分钟前
基于Java+VUE+MariaDB实现(Web)仿小米商城
java·前端·vue.js
袁煦丞1 小时前
低成本私有云存储方案Nas-Cab:cpolar实验室第508次成功挑战
前端·程序员·远程工作
小公主1 小时前
「前端必备」Flex 布局全解析:从入门到深度计算,搞懂弹性盒子!
前端·css
江城开朗的豌豆1 小时前
前端性能救星!用 requestAnimationFrame 丝滑渲染海量数据
前端·javascript·面试
江城开朗的豌豆1 小时前
src和href:这对'双胞胎'属性,你用对了吗?
前端·javascript·面试
江城开朗的豌豆1 小时前
forEach遇上await:你的异步代码真的在按顺序执行吗?
前端·javascript·面试