JS 底层探究-- 普通函数和构造函数
一、核心理论
1. 普通函数 vs 构造函数
- 普通函数:小驼峰命名
getUser(),直接调用,返回数据 / 执行逻辑
例如:
function getUser (name) { retrun {name}; }- 构造函数:大驼峰命名
User(),必须用new调用,用来创建对象
例如:
// 构造函数(大驼峰命名) function Person(name, age) { // 自身属性 this.name = name; this.age = age; }2. new 关键字四大步骤
- 创建一个空对象
{} - 这个空对象的
__proto__指向构造函数的prototype - 构造函数内部的
this指向这个空对象 - 如果构造函数没有返回对象,则默认返回这个新对象
// 1. 先定义一个构造函数 function Person(name, age) { // 步骤3执行时,this 会变成我们创建的空对象 this.name = name; this.age = age; } // ------------------------------ // 核心:手写模拟 new 的4大步骤 // ------------------------------ function myNew(constructor, ...args) { // 步骤1:创建一个空对象 {} const obj = {}; // 步骤2:空对象的 __proto__ 指向构造函数的 prototype obj.__proto__ = constructor.prototype; // 步骤3:执行构造函数,让 this 指向这个空对象 // call 的作用:把构造函数里的 this 改成 obj const result = constructor.call(obj, ...args); // 步骤4:如果构造函数没有返回对象,就返回我们创建的 obj if (result && typeof result === "object") { return result; } else { return obj; } } // ------------------------------ // 测试使用 // ------------------------------ const p1 = myNew(Person, "小明", 18); console.log(p1); // Person { name: '小明', age: 18 } console.log(p1.name); // 小明3. 实例与构造函数关系
new 构造函数()→ 得到实例对象
const a = new Person("XIAO MIN", 20);- 多个实例之间互相独立
const b = new Person("XIAO HUA", 29) console.log(a); // Person { name: 'XIAO MIN', age: 20 } console.log(b); // Person { name: 'XIAO HUA', age: 29 }4. 自身属性 vs 原型属性
- 自身属性:
this.xxx挂载的属性,每个实例独立拥有
console.log(a.name); // XIAO MIN Person.prototype.pName = "Person" console.log(a.pName); // Person- 原型属性:在
构造函数.prototype上,所有实例共享
console.log(b.name) // XIAO HUA console.log(b.pName) // Person