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

相关推荐
正小安1 小时前
如何在微信小程序中实现分包加载和预下载
前端·微信小程序·小程序
吾爱星辰2 小时前
Kotlin 处理字符串和正则表达式(二十一)
java·开发语言·jvm·正则表达式·kotlin
ChinaDragonDreamer2 小时前
Kotlin:2.0.20 的新特性
android·开发语言·kotlin
IT良2 小时前
c#增删改查 (数据操作的基础)
开发语言·c#
Kalika0-03 小时前
猴子吃桃-C语言
c语言·开发语言·数据结构·算法
_.Switch3 小时前
Python Web 应用中的 API 网关集成与优化
开发语言·前端·后端·python·架构·log4j
一路向前的月光3 小时前
Vue2中的监听和计算属性的区别
前端·javascript·vue.js
长路 ㅤ   3 小时前
vite学习教程06、vite.config.js配置
前端·vite配置·端口设置·本地开发
长路 ㅤ   3 小时前
vue-live2d看板娘集成方案设计使用教程
前端·javascript·vue.js·live2d
代码雕刻家3 小时前
课设实验-数据结构-单链表-文教文化用品品牌
c语言·开发语言·数据结构