资讯专栏INFORMATION COLUMN

为啥我要自己实现一个new语法糖?

andycall / 3342人阅读

摘要:为啥我要自己实现一个语法糖为什么要自己实现一个语法糖呢因为之前对于里的语法糖一直是理论理解但是并亲自尝试实现过。直到有一天在头条的面试中我聊了摸着自己的良心说我可以实现一个语法糖面试官嗯那你实现一个吧。我们知道构造函数一般是不写的。

为啥我要自己实现一个new语法糖?
为什么要自己实现一个new语法糖呢?

因为之前对于JS里的new语法糖一直是理论理解,但是并亲自尝试实现过。

直到有一天,在头条的面试中 我聊high了,摸着自己的良心说: 我可以实现一个new语法糖!

面试官: 嗯,那你实现一个吧。

我: ...咱要不聊点别的?

步骤1: 观察new做了哪些事?

先随便用一下new,然后观察、脑补、想象,最后猜一下new可能干了点什么勾当!

    function Human(){
        this.type = "human"
        this.age = 18
    }

    var human1 = new Human()
    console.log(h1)  // {type:"human",age:18}

掐指一算,先不管怎么做,直觉上new大概做了这样几件事情

创建一个空对象

让空对象的__proto__指向构造函数的prototype,并且this指向这个对象

偷偷return这个对象

function Human(){
            // var obj = {}                         创建了一个空对象
            // obj.__proto__ = Human.prototype      让空对象的__proto__指向构造函数的prototype
            // this = obj                           obj赋值给this
            this.type = "human"
            this.age = 18

            // return this                          偷偷帮你return这个对象
        }

        var human1 = new Human()
        console.log(h1)  // {type:"human",age:18}
步骤2: 设计一下接口

面向接口编程嘛,设计一个程序,先思考最后是以什么形式调用呢? 毕竟我们不是JS之父,没法真的去创造语法。

我们打算封装一个函数newFn(),可以用来创建实例对象,然后它最终是这样来用的:

下面是伪代码

 function Human(){
        this.type = "human"
        this.age = 18
    }

 // var human1 = new Human()     不用new了,我们用newFn()来创建实例
 
 function newFn(){
    ... 写一些代码
 }
 
 var human1 = newFn(Human)   
步骤3: 实现newFn()

那么newFn()的输入和输出是什么呢?

参数: Constructor和数量不定的参数。我们肯定得知道是创造哪个构造函数的实例吧,所以至少需要一个Constructor,同时也可以自定义一些参数

返回: 返回一个obj,也即是构造函数的实例

      function newFn() {
            const obj = {};
            const Constructor = [].shift.call(arguments)            // 通过arguments取出第一个参数 Constructor ,并截取掉arguments第一个参数,方便之后使用   
            obj.__proto__ = Constructor.prototype;                  // 让这个obj继承一下Constructor原型链上的东西
            Constructor.apply( obj, arguments )                     // 这里是obj借用一下Constructor这个方法,从而给obj添加type 和 age

            return obj                                              // 返回对象
        }
        
        
     注: shift() 方法用于把数组的第一个元素从其中删除,并返回第一个元素的值。
Example: 使用newFn去创造一个实例 (可以拿到浏览器测试用)
        function newFn() {
            const obj = {};
            const Constructor = [].shift.call(arguments)
            obj.__proto__ = Constructor.prototype;
            Constructor.apply( obj, arguments )
            return obj
        }


        function Human() {
            this.type = "human"
            this.age = 18
        }

        var human1 = newFn( Human )

        console.log( human1 )

可以发现human1这个实例,跟我们用new语法创造出来的是一个效果。

小小的补充修改

为了让newFn跟new的行为表现更加相似,需要做一点点修改完善。

我们知道,构造函数一般是不写return的。它偷偷自动给你return一个实例对象

但是如果,我们手动return呢? 2个情况

return 了一个基本数据类型,不会返回这个简单数据类型, 依旧帮你return一个实例对象

return 了一个对象,那么就返回你这个对象。不再帮你return实例对象

所以,为了实现同样的效果,newFn修改一行代码

    function newFn() {
        const obj = {};
        const Constructor = [].shift.call(arguments)
        obj.__proto__ = Constructor.prototype;
        const result = Constructor.apply( obj, arguments ) // 接受一下构造函数的返回值,是对象就return该对象,否则还是return实例对象

        return typeof result === "object" ? result : obj
    }

Example: 使用完善后的newFn去创造一个实例 (可以拿到浏览器测试用)
        function newFn() {
            const obj = {};
            const Constructor = [].shift.call( arguments )
            obj.__proto__ = Constructor.prototype;
            const result = Constructor.apply( obj, arguments ) // 接受一下构造函数的返回值,是对象就return该对象,否则还是return实例对象

            return typeof result === "object" ? result : obj
        }


        function Human( name, age ) {
            this.type = "human"
            this.age = 18
            return {
                name: name,
                age: age
            }
        }

        var human1 = newFn( Human, "ziwei", "24" )

        console.log( human1 )

更多文章,可关注https://github.com/ziwei3749/...

如果有疑问或者发现错误,可以在相应的 issues 进行提问或勘误。

如果喜欢或者有所启发,欢迎 star,对作者也是一种鼓励。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/94353.html

相关文章

  • webpack多页应用架构系列(八):教练我要写ES6!webpack怎么整合Babel?

    摘要:本文首发于的技术博客实用至上,非经作者同意,请勿转载。只是最近学习生态,用起来转换之余,也不免碰到诸多用上的教程案例,因此便稍作学习。在当前的浏览器市场下,想在生产环境用上,是必不可少的。 本文首发于Array_Huang的技术博客——实用至上,非经作者同意,请勿转载。原文地址:https://segmentfault.com/a/1190000006992218如果您对本系列文章感兴...

    gnehc 评论0 收藏0
  • JS面向对象之五 【继承】

    摘要:首先为了模拟类创建对象的功能搞出了构造函数。也就是名字肤色肤色这里是继承里的自有属性生命值这里继承的共有属性的方法攻击力兵种美国大兵攻击防御死亡肤色 JS面向对象之五 【继承】 我们已经准备了很多前置知识,包括 原型链,对象和对象之间的关系 this,对象和函数之间的关系 new, 用函数批量创建特定的对象的语法糖 JS面向对象的前世今生 我们说,面向对象是一种写代码的套路。因为如...

    genefy 评论0 收藏0
  • Hollis原创|不了解这12个语法,别说你会Java

    摘要:但其实,虚拟机并不支持这些语法糖。方式为每个泛型类型创建唯一的字节码表示,并且将该泛型类型的实例都映射到这个唯一的字节码表示上。GitHub 2.5k Star 的Java工程师成神之路 ,不来了解一下吗); GitHub 2.5k Star 的Java工程师成神之路 ,真的不来了解一下吗); GitHub 2.5k Star 的Java工程师成神之路 ,真的确定不来了解一下吗); 本文从 ...

    番茄西红柿 评论0 收藏0
  • Hollis原创|不了解这12个语法,别说你会Java

    摘要:但其实,虚拟机并不支持这些语法糖。方式为每个泛型类型创建唯一的字节码表示,并且将该泛型类型的实例都映射到这个唯一的字节码表示上。GitHub 2.5k Star 的Java工程师成神之路 ,不来了解一下吗); GitHub 2.5k Star 的Java工程师成神之路 ,真的不来了解一下吗); GitHub 2.5k Star 的Java工程师成神之路 ,真的确定不来了解一下吗); 本文从 ...

    番茄西红柿 评论0 收藏0
  • Hollis原创|不了解这12个语法,别说你会Java

    摘要:但其实,虚拟机并不支持这些语法糖。方式为每个泛型类型创建唯一的字节码表示,并且将该泛型类型的实例都映射到这个唯一的字节码表示上。GitHub 2.5k Star 的Java工程师成神之路 ,不来了解一下吗); GitHub 2.5k Star 的Java工程师成神之路 ,真的不来了解一下吗); GitHub 2.5k Star 的Java工程师成神之路 ,真的确定不来了解一下吗); 本文从 ...

    yy13818512006 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<