先说大前提大结论:
JS中万物皆对象
一、对象
创建对象的方法
- 字面量创建
// 字面量格式
const obj3 = {
uname: '字面量格式',
}
new Object()
// new 方法格式
const obj = new Object()
obj.uname = 'new方法'
console.log(obj)
// new简写格式
const obj2 = new Object({ uname: 'new方法简写格式' })
new构造函数
自定义构造函数创建:可以快速创建多个对象
约定:
- 命名必须以大写字母开头
- 只能用 new 操作符执行
- 内部使用
this指向新实例化的对象- 不需要
return,否则则变为普通函数
代码示例:
function Pig (uname, age) {
this.uname = uname
this.age = age
}
const p = new Pig('佩奇', 6)
追问:为什么一个看起来普普通通的函数使用了new就产生了一个新的对象?
那么接下来我们就来讨论一下new到底在函数中做了什么:
new做了什么
- 创建一个空对象
- 让构造函数的 this 指向这个空对象
- 执行构造函数中的代码
- 将这个空对象的隐式原型
__proto__赋值成 构造函数的原型对象--原型的原理 - 返回这个对象
手动模拟一下
// 手动模拟 new 的过程
function Person(name, age, sex) {
var _this = {} // 步骤1、2:创建空对象,修改this指向
_this.name = name; // 步骤3:执行代码
_this.age = age;
_this.sex = sex;
return _this; // 步骤4:返回对象
}
二、包装类
- 用户定义的字面量,会自动被JS转换为对应的包装类
- 包装类的实例对象在参与计算时,会被自动拆解为基本类型 (例如:
Number) JS弱类型语言,只有在赋值语句执行时才会判断值的类型- 引擎在运行中将值判定为原始类型时,会自动将包装对象上添加的属性移除
这里给出一些常见数据的包装类
| 原始类型 | 包装对象 | 示例 |
|---|---|---|
| number | Number | new Number(42) |
| string | String | new String("hello") |
| boolean | Boolean | new Boolean(true) |
| symbol | Symbol | Symbol("desc") |
| bigint | BigInt | BigInt(9007199254740991) |
包装类的特性
众所周知,属性和方法是对象独有的,基本数据类型是不可以拥有属性的,所以会出现这种情况
// 基本类型
var num = 123;
num.a = 'aaa'; // 在基本数据中添加一个属性'a'
console.log(num.a); // undefined
// 对象类型
var num = new Number(123);
num.a = 'aaa'; // 在对象中添加一个属性'a'
console.log(num.a); // 'aaa'
追问1:为什么同样是简单数据,str可以直接用.length方法?方法和属性不是复杂数据类型专属吗?
var str = 'FWB';
console.log(str.length); // 3
其实按代码来看,str中的length方法其实不是我们自己添加进去的,这个地方是使用了String原型的既定方法,涉及到了原型和原型链的知识点
表面上看以为是用了直接挂载到简单数据类型上的方法或属性,其实本质上我们使用的并不是直接挂载到简单数据类型上的方法或者属性,是引擎帮我们通过原型链找到了我们需要的资源
小测试
var arr = [1, 2, 3, 4, 5]
arr.length = 2
console.log(arr); // [1, 2]
var str = 'abcd' // let str = new String('abcd')
str.length = 2
// delete str.length
console.log(str.length); // 'abcd'
聪明的你已经猜到了,形成上面结果的原因其实是
arr数组是对象,length可被操作,修改会直接影响对应数据的长度str是字面量数据,length方法为只读,无法修改,数据长度仍然正常
追问2:V8是怎么判断数据类型的?
判断数据类型
typeof:判断基本数据类型,可以准确判断除了null和function外的所有类型
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"
null被判定为object是因为JavaScript早期版本中,所有值存储在32位单元中,其中object的标识码为 000,而null的机器码全为0,导致低位也为0,从而 typeof null 返回object
其他判断类型方法
| 工具 | 适用范围 | 缺陷 |
|---|---|---|
typeof | 基本类型(除了null) | 对象类型都是"object" |
instanceof | 对象类型 | 基本类型无能为力 |
Object.prototype.toString.call() | 万能侦探 | 写法稍显复杂 |