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

相关推荐
jiangzhihao05153 小时前
前端自动翻译插件webpack-auto-i18n-plugin的使用
前端·webpack·node.js
软件技术NINI5 小时前
html css网页制作成品——HTML+CSS盐津铺子网页设计(5页)附源码
前端·css·html
R-G-B5 小时前
【02】C#入门到精通——C# 变量、输入/输出、类型转换
开发语言·c#·c# 变量·c#输入/输出·c#类型转换
星河队长5 小时前
C# 软件加密方法,有使用时间限制,同时要防止拷贝
开发语言·c#
史迪奇_xxx5 小时前
10、一个简易 vector:C++ 模板与 STL
java·开发语言·c++
2301_801252225 小时前
Java中的反射
java·开发语言
Kiri霧6 小时前
Rust开发环境搭建
开发语言·后端·rust
weixin-a153003083166 小时前
[数据抓取-1]beautifulsoup
开发语言·python·beautifulsoup
mapbar_front6 小时前
面试问题—我的问题问完了,你还有什么想问我的吗?
前端·面试
quweiie6 小时前
thinkphp8+layui多图上传,带删除\排序功能
前端·javascript·layui