欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 健康 > 养生 > 手写 JavaScript 中的 new 关键字

手写 JavaScript 中的 new 关键字

2025/9/26 15:52:48 来源:https://blog.csdn.net/m0_72030584/article/details/144616238  浏览:    关键词:手写 JavaScript 中的 new 关键字

new 关键字

在 JavaScript 中,new 关键字用于创建一个用户自定义的对象类型的实例或具有构造函数的内置对象类型之一。具体来说,new 关键字做了以下几件事:

  1. 创建一个新的空对象
  2. 将这个新对象的原型设置为构造函数的 prototype 属性
  3. 将构造函数内部的 this 绑定到这个新对象
  4. 执行构造函数内的代码
  5. 返回这个新对象(除非构造函数显式返回另一个对象)。

手动实现 new 关键字

步骤 1: 创建一个新的空对象

使用 Object.create(null) 创建一个没有任何原型的新对象。这样做是为了避免默认的 Object.prototype 方法和属性干扰我们的实现。

步骤 2: 设置新对象的原型

将新对象的原型设置为构造函数的 prototype 属性。这一步确保新对象继承自构造函数的原型链。

步骤 3: 绑定构造函数内部的 this

使用 apply 或 call 方法将构造函数内部的 this 绑定到新创建的对象。这样,构造函数内部的所有操作都会针对新对象进行。

步骤 4: 执行构造函数

调用构造函数,使其内部的逻辑得以执行。构造函数可以初始化新对象的属性和其他成员。

步骤 5: 返回新对象

检查构造函数的返回值。如果构造函数显式返回一个对象,则返回该对象;否则,返回新创建的对象。

myNew 函数实现

function myNew(constructor, ...args) {// Step 1: 创建一个新的空对象,其原型指向构造函数的 prototype 属性const instance = Object.create(constructor.prototype);// Step 2: 将构造函数内部的 this 绑定到新对象,并执行构造函数const result = constructor.apply(instance, args);// Step 3: 检查构造函数的返回值// 如果返回的是一个对象,则返回该对象;否则返回新创建的对象return (result !== null && typeof result === 'object') ? result : instance;
}

使用 myNew 创建对象

// 定义一个构造函数返回对象
function PersonWithReturn(name, age) {this.name = name;this.age = age;return { customProperty: 'customValue' };
}// 使用 myNew 创建 PersonWithReturn 的实例
const personWithReturn = myNew(PersonWithReturn, 'Charlie', 40);console.log(personWithReturn); // 输出: { customProperty: 'customValue' }
console.log(personWithReturn instanceof PersonWithReturn); // 输出: false

构造函数返回对象的情况

// 定义一个构造函数 Person
function Person(name, age) {this.name = name;this.age = age;
}// 使用 myNew 创建 Person 的实例
const person1 = myNew(Person, 'Alice', 30);
const person2 = myNew(Person, 'Bob', 25);console.log(person1); // 输出: Person { name: 'Alice', age: 30 }
console.log(person2); // 输出: Person { name: 'Bob', age: 25 }console.log(person1 instanceof Person); // 输出: true
console.log(person2 instanceof Person); // 输出: true

构造函数返回原始值的情况

// 定义一个构造函数返回原始值
function PersonWithPrimitiveReturn(name, age) {this.name = name;this.age = age;return 'primitive value';
}// 使用 myNew 创建 PersonWithPrimitiveReturn 的实例
const personWithPrimitiveReturn = myNew(PersonWithPrimitiveReturn, 'David', 35);console.log(personWithPrimitiveReturn); // 输出: PersonWithPrimitiveReturn { name: 'David', age: 35 }
console.log(personWithPrimitiveReturn instanceof PersonWithPrimitiveReturn); // 输出: true

完整代码

//myNew.js
/*** 手动实现 new 关键字的功能* @param {Function} constructor - 构造函数* @param {...any} args - 传递给构造函数的参数* @returns {Object} - 新创建的对象实例*/
function myNew(constructor, ...args) {if (typeof constructor !== 'function') {throw new TypeError('Constructor must be a function');}// Step 1: 创建一个新的空对象,其原型指向构造函数的 prototype 属性const instance = Object.create(constructor.prototype);// Step 2: 将构造函数内部的 this 绑定到新对象,并执行构造函数const result = constructor.apply(instance, args);// Step 3: 检查构造函数的返回值// 如果返回的是一个对象,则返回该对象;否则返回新创建的对象return (result !== null && (typeof result === 'object' || typeof result === 'function')) ? result : instance;
}export default myNew;
// 导入 myNew 函数
import myNew from './myNew.js';// 定义一个构造函数 Person
function Person(name, age) {this.name = name;this.age = age;
}// 使用 myNew 创建 Person 的实例
const person1 = myNew(Person, 'Alice', 30);
const person2 = myNew(Person, 'Bob', 25);console.log(person1); // 输出: Person { name: 'Alice', age: 30 }
console.log(person2); // 输出: Person { name: 'Bob', age: 25 }console.log(person1 instanceof Person); // 输出: true
console.log(person2 instanceof Person); // 输出: true// 定义一个构造函数返回对象
function PersonWithReturn(name, age) {this.name = name;this.age = age;return { customProperty: 'customValue' };
}// 使用 myNew 创建 PersonWithReturn 的实例
const personWithReturn = myNew(PersonWithReturn, 'Charlie', 40);console.log(personWithReturn); // 输出: { customProperty: 'customValue' }
console.log(personWithReturn instanceof PersonWithReturn); // 输出: false// 定义一个构造函数返回原始值
function PersonWithPrimitiveReturn(name, age) {this.name = name;this.age = age;return 'primitive value';
}// 使用 myNew 创建 PersonWithPrimitiveReturn 的实例
const personWithPrimitiveReturn = myNew(PersonWithPrimitiveReturn, 'David', 35);console.log(personWithPrimitiveReturn); // 输出: PersonWithPrimitiveReturn { name: 'David', age: 35 }
console.log(personWithPrimitiveReturn instanceof PersonWithPrimitiveReturn); // 输出: true

总结

  1. 创建新对象: 使用 Object.create(constructor.prototype) 创建新对象。
  2. 绑定 this: 使用 constructor.apply(instance, args) 将构造函数内部的 this 绑定到新对象。
  3. 处理返回值: 检查构造函数的返回值,如果是对象则返回该对象,否则返回新创建的对象。
  4. 验证实例: 使用 instanceof 验证新创建的对象是否是构造函数的实例。

与vue项目结合

project-root/

├── src/

│ ├── main.js

│ ├── Chronicle.js

│ ├── myNew.js

│ └── views/

│ └── ChronicleIndex.vue

├── public/

│ └── index.html

└── package.json


// myNew.js
/*** 手动实现 new 关键字的功能* @param {Function} constructor - 构造函数* @param {...any} args - 传递给构造函数的参数* @returns {Object} - 新创建的对象实例*/
function myNew(constructor, ...args) {if (typeof constructor !== 'function') {throw new TypeError('Constructor must be a function');}// Step 1: 创建一个新的空对象,其原型指向构造函数的 prototype 属性const instance = Object.create(constructor.prototype);// Step 2: 将构造函数内部的 this 绑定到新对象,并执行构造函数const result = constructor.apply(instance, args);// Step 3: 检查构造函数的返回值// 如果返回的是一个对象,则返回该对象;否则返回新创建的对象return (result !== null && (typeof result === 'object' || typeof result === 'function')) ? result : instance;
}export default myNew;
//Chronicle.js
class Chronicle {constructor(title, entries) {this.title = title;this.entries = entries || [];}addEntry(entry) {this.entries.push(entry);}getEntries() {return this.entries;}getTitle() {return this.title;}
}export default Chronicle;
//main.js
// 导入 myNew 函数
import myNew from './myNew.js';
// 导入 Chronicle 类
import Chronicle from './Chronicle.js';// 使用 myNew 创建 Chronicle 的实例
const chronicle1 = myNew(Chronicle, 'Daily Chronicles', ['First entry']);
const chronicle2 = myNew(Chronicle, 'Weekly Chronicles');// 测试 chronicle1
console.log(chronicle1.getTitle()); // 输出: Daily Chronicles
console.log(chronicle1.getEntries()); // 输出: ['First entry']chronicle1.addEntry('Second entry');
console.log(chronicle1.getEntries()); // 输出: ['First entry', 'Second entry']// 测试 chronicle2
console.log(chronicle2.getTitle()); // 输出: Weekly Chronicles
console.log(chronicle2.getEntries()); // 输出: []chronicle2.addEntry('First weekly entry');
console.log(chronicle2.getEntries()); // 输出: ['First weekly entry']// 验证实例类型
console.log(chronicle1 instanceof Chronicle); // 输出: true
console.log(chronicle2 instanceof Chronicle); // 输出: true
//ChronicleIndex.vue
<template><div><h1>{{ chronicle.getTitle() }}</h1><ul><li v-for="(entry, index) in chronicle.getEntries()" :key="index">{{ entry }}</li></ul><input v-model="newEntry" placeholder="Add new entry" /><button @click="addEntry">Add Entry</button></div>
</template><script setup>
import { ref, onMounted } from 'vue';
import myNew from '../path/to/myNew.js'; // 根据实际路径调整
import Chronicle from '../path/to/Chronicle.js'; // 根据实际路径调整// 使用 myNew 创建 Chronicle 的实例
const chronicle = myNew(Chronicle, 'My Chronicle');// 输入框绑定的值
const newEntry = ref('');// 添加条目的方法
function addEntry() {if (newEntry.value.trim()) {chronicle.addEntry(newEntry.value);newEntry.value = ''; // 清空输入框}
}// 生命周期钩子
onMounted(() => {console.log('Chronicle component mounted');
});
</script><style scoped>
/* 样式可以根据需要添加 */
h1 {color: #333;
}ul {list-style-type: none;padding: 0;
}li {background-color: #f0f0f0;margin: 5px 0;padding: 10px;border-radius: 5px;
}input {padding: 5px;width: calc(100% - 22px);margin-bottom: 10px;
}button {padding: 5px 10px;cursor: pointer;
}
</style>
// src/main.js
import { createApp } from 'vue';
import App from './App.vue';
import ChronicleIndex from './views/ChronicleIndex.vue';const app = createApp(App);app.component('ChronicleIndex', ChronicleIndex);app.mount('#app');

总结

  1. 手动实现 new 关键字:

    • 创建一个新的空对象。
    • 设置新对象的原型。
    • 绑定构造函数内部的 this
    • 执行构造函数。
    • 处理构造函数的返回值。
  2. 封装类:

    • 定义一个类,包含构造函数和方法。
    • 使用 myNew 手动创建类的实例。
  3. 在 Vue 组件中使用:

    • 导入 myNew 和类。
    • 在 setup 函数中使用 myNew 创建实例。
    • 在模板中绑定数据和事件。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词