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

相关推荐
一知半解仙4 分钟前
2026年彻底免费的辅助编程Agent大模型汇总
开发语言·人工智能·开源
Mr-Wanter17 分钟前
wsl2 jdk管理工具之sdkman
java·开发语言·sdkman
2502_9212860725 分钟前
【企业网络管理】DHCP 与 SAMBA:从协议原理到企业级实战配置全解析
开发语言·php
矮小的方盒27 分钟前
关于大型网站技术演进的思考(一)--存储的瓶颈(1)
开发语言
Maiko Star30 分钟前
Python核心语法——函数
开发语言·python
大气的小蜜蜂1 小时前
基于Python+Django的健身房管理系统实现:核心亮点全流程解析
开发语言·python·django
天空'之城1 小时前
Linux 系统编程 04:进程基础
linux·开发语言·进程基础
2501_943782352 小时前
【共创季稿事节】猜数字游戏:二分法思维与交互式反馈
前端·游戏·microsoft·harmonyos·鸿蒙·鸿蒙系统
2zcode2 小时前
免费开源项目文档:基于MATLAB图像处理的药片检测与计数系统设计与实现
开发语言·图像处理·matlab