《前端面试题》- 编程题-手写new(JS)

复制代码
function Person(name) {
    this.name = name;
}

Person.prototype.say = function() {
    console.log(`I'm ${this.name}`);
}


const xiaoming = new Person('xiaoming');
xiaoming.say();
// 输出
// I'm xiaoming

function _new(fn, ...args) {
    // 基于fn的原型创建一个新的对象
    const emptyObj = Object.create(fn.prototype);

  // 添加属性到新创建的emptyObj上, 并获取fn函数执行的结果.
    const newObj = fn.apply(emptyObj, args);

    // 如果执行结果有返回值并且是一个对象, 返回执行的结果, 否则, 返回新创建的对象
    return newObj instanceof Object ? newObj : emptyObj;
}

const xiaohong = _new(Person, 'xiaohong');
xiaohong.say(); 
// 输出
//  I'm xiaohong

注意

这里使用构造函数的方式定义,不要使用class的方式定义,如下:

复制代码
class Person {
    constructor(name) {
        this.name = name;
    }

    say() {
        console.log(this.name);
    }
}


const xiaoming = new Person('xiaoming');
xiaoming.say();

function _new(fn, ...args) {
    const emptyObj = Object.create(fn.prototype);
    const newObj = fn.apply(emptyObj, args);
    return newObj instanceof Object ? newObj : emptyObj;
}

const xiaohong = _new(Person, 'xiaohong');
xiaohong.say(); 

// /data/161414204943248864.js:19
//     const newObj = fn.apply(emptyObj, args);
//                       ^

// TypeError: Class constructor Person cannot be invoked without 'new'
//     at _new (/data/161414204943248864.js:19:23)
//     at Object. (/data/161414204943248864.js:23:18)
//     at Module._compile (internal/modules/cjs/loader.js:776:30)
//     at Object.Module._extensions..js (internal/modules/cjs/loader.js:787:10)
//     at Module.load (internal/modules/cjs/loader.js:653:32)
//     at tryModuleLoad (internal/modules/cjs/loader.js:593:12)
//     at Function.Module._load (internal/modules/cjs/loader.js:585:3)
//     at Function.Module.runMain (internal/modules/cjs/loader.js:829:12)
//     at startup (internal/bootstrap/node.js:283:19)
//     at bootstrapNodeJSCore (internal/bootstrap/node.js:622:3)

原因

虽然class和es5中的构造函数创建的对象,在使用上是一样的,但是还是有些不同的,在报错中很明显可以看出fn.apply这里出错了。注意下面不同的最后两点。

class和es5构造函数的区别

  • class在语法上更加贴合面向对象的写法, Class实现继承更加易读、易理解
  • class声明内部会启用严格模式
  • class的所有方法都是不可枚举的
  • class的所有方法都没有原型对象prototype
  • class定义的类不能被当做函数调用

参考网址:https://segmentfault.com/a/1190000022076671

相关推荐
牛奶5 分钟前
AI辅助开发的基础概念
前端·人工智能·ai编程
摸鱼的春哥8 分钟前
Agent教程15:认识LangChain,Agent框架的王(上)
前端·javascript·后端
明月_清风1 小时前
自定义右键菜单:在项目里实现“选中文字即刻生成新提示”
前端·javascript
明月_清风1 小时前
告别后端转换:高质量批量导出实战
前端·javascript
刘发财6 小时前
弃用html2pdf.js,这个html转pdf方案能力是它的几十倍
前端·javascript·github
牛奶8 小时前
2026年大模型怎么选?前端人实用对比
前端·人工智能·ai编程
牛奶8 小时前
前端人为什么要学AI?
前端·人工智能·ai编程
Kagol11 小时前
🎉OpenTiny NEXT-SDK 重磅发布:四步把你的前端应用变成智能应用!
前端·开源·agent
GIS之路12 小时前
ArcGIS Pro 中的 notebook 初识
前端
JavaGuide12 小时前
7 道 RAG 基础概念知识点/面试题总结
前端·后端