《前端面试题》- 编程题-手写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

相关推荐
工业甲酰苯胺12 分钟前
实现 json path 来评估函数式解析器的损耗
java·前端·json
老前端的功夫13 分钟前
Web应用的永生之术:PWA落地与实践深度指南
java·开发语言·前端·javascript·css·node.js
LilySesy42 分钟前
ABAP+WHERE字段长度不一致报错解决
java·前端·javascript·bug·sap·abap·alv
ᐇ9591 小时前
Java HashMap深度解析:数据结构、原理与实战指南
java·开发语言·数据结构
QT 小鲜肉2 小时前
【个人成长笔记】在 Linux 系统下撰写老化测试脚本以实现自动压测效果(亲测有效)
linux·开发语言·笔记·单片机·压力测试
Wang's Blog2 小时前
前端FAQ: Vue 3 与 Vue 2 相⽐有哪些重要的改进?
前端·javascript·vue.js
程序员龙一2 小时前
C++之static_cast关键字
开发语言·c++·static_cast
yue0082 小时前
C# 分部类读取学生信息
开发语言·c#
奶茶树2 小时前
【C++/STL】map和multimap的使用
开发语言·c++·stl
再希2 小时前
React+Tailwind CSS+Shadcn UI
前端·react.js·ui