资讯专栏INFORMATION COLUMN

Babel转码关于 "super" 的注意事项

rose / 1082人阅读

摘要:事情的起因是在问答上看到一个朋友的提问,问的是阮一峰老师入门上关于关键字的一段代码问题,下面是这个代码的截图这位楼主说他觉得的值不是,下面有网友说把代码粘贴到控制台一试就是这结果没错,后来楼主说是他想错了。

事情的起因是在问答上看到一个朋友的提问,问的是阮一峰老师 ECMAScript 6 入门 上关于super关键字的一段代码问题,下面是这个代码的截图:

这位楼主说他觉得 this.x 的值不是3,下面有网友说把代码粘贴到 chrome 控制台一试就是这结果没错,后来楼主说是他想错了。我也顺便把代码粘贴到 chome 下执行后答案也确实是3。

本来这个事没啥就结束了,正好我开着 WebStorm 准备写代码,顺手粘贴到代码文件里面,保存 > webpack打包 > 刷新浏览器,瞅了一眼 Console:

!这是神马情况,输出竟然是2!

问题分析

为啥与 chrome 直接运行的结果不一致呢?想了想问题应该出在 Babel 转码上。马上打开转码后的文件,定位到这段代码的位置:

var B = function (_A) {
    _inherits(B, _A);

    function B() {
        _classCallCheck(this, B);

        var _this = _possibleConstructorReturn(this, (B.__proto__ || Object.getPrototypeOf(B)).call(this));

        _this.x = 2;
        _set(B.prototype.__proto__ || Object.getPrototypeOf(B.prototype), "x", 3, _this);
        console.log(_get(B.prototype.__proto__ || Object.getPrototypeOf(B.prototype), "x", _this)); // undefined
        console.log(_this.x); // 3
        return _this;
    }

    return B;
}(A);

super.x = 3; 对应的是 _set(B.prototype.__proto__ || Object.getPrototypeOf(B.prototype), "x", 3, _this); 这里有个 _set() 函数,再看下这个 _set() 是啥:

var _set = function set(object, property, value, receiver) {
    var desc = Object.getOwnPropertyDescriptor(object, property);
    if (desc === undefined) {
        var parent = Object.getPrototypeOf(object);
        if (parent !== null) {
            set(parent, property, value, receiver);
        }
    } else if ("value" in desc && desc.writable) {
        desc.value = value;
    } else {
        var setter = desc.set;
        if (setter !== undefined) {
            setter.call(receiver, value);
        }
    }
    return value;
};

仔细看看这个函数后,明白是怎么回事了。结合阮一峰老师的代码和上面的转码可以看出,_set() 传进来的第一个参数是 B.prototype.__proto__ -- 也就是A的原型对象 -- A.prototype,第一句代码会先找 x属性 的描述符,如果找不到继续顺着原型链找... 当然是找不到的了,所以相当于啥也没执行,this.x 的值依然是2。

如果按照这个 _set() 函数的逻辑,在什么情况下 this.x 的值才会是3呢?要满足两个条件:

A.prototype 上必须有 x 属性定义

这个 x 属性定义上还必须定义 set 访问器

比如像下面这样:

Object.defineProperty(A.prototype, "x", {
    get: function () {
        return this._x;
    },
    set: function (value) {
        this._x = value;
    }
});

然后再跑一把,果然 this.x 的值是3了!等一下... 怎么 console.log(super.x); // undefined 这句的结果不是 undefined 也是3了呢?看下转码那里还有个 _get() 函数:

var _get = function get(object, property, receiver) {
    if (object === null) object = Function.prototype;
    var desc = Object.getOwnPropertyDescriptor(object, property);
    if (desc === undefined) {
        var parent = Object.getPrototypeOf(object);
        if (parent === null) {
            return undefined;
        } else {
            return get(parent, property, receiver);
        }
    } else if ("value" in desc) {
        return desc.value;
    } else {
        var getter = desc.get;
        if (getter === undefined) {
            return undefined;
        }
        return getter.call(receiver);
    }
};

好吧,代码走到最后 else 的 getter 那里了,自然 super.x 的读取结果就是3了

目前还没时间看为啥 Babel 要这么转码处理,如果你有答案了欢迎留言讨论。

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

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

相关文章

  • react项目关于webpack配置修改

    一、前言通过CRA脚手架构建的项目,一般webpack配置是隐藏的,如果要修改,就要另外处理。想要修改webpack通常有两种方式通过插件去增加或覆盖webpack配置(方法一、方法二)或者释放项目中的webpack配置,使之可见,然后可以修改(方法三)本来CRA脚手架将webpack等复杂的配置封装在项目中,后续可以通过更新react-scripts来体验版本升级带来的新特性,但有些时候确实需要...

    社区管理员 评论0 收藏0
  • 煦涵说Webpack-IE低版本兼容指南

    摘要:,是一个前端资源加载打包工具,现在版本已经到,今天的文章不支持介绍的及使用,而是对最近项目开发中使用打包时处理低版本及以下浏览器兼容问题做一次总结。 Webpack,Webpack 是一个前端资源加载/打包工具,现在版本已经 release 到 v2.6.1,今天的文章不支持介绍Webpack的API及使用,而是对最近项目开发中使用Webpack打包时处理IE低版本(IE8及以下)浏览...

    tanglijun 评论0 收藏0
  • 如何使用pandas对超大csv文件进行快速拆分详解

      小编写这篇文章的主要目的,主要是对pandas做一个较为详细的一个解答,pandas其实就是一个数据模型库,里面的内容还是比较的多的,那么,怎么样对海量的数据进行处理呢?处理的内容就是对超大的csv文件进行快速拆分,下面就给大家举例验证。  前言  本文介绍如何利用pandas对超大CSV文件进行快速拆分。  1.操作步骤  1.1安装pandas  pipinstallpandas  1.2...

    89542767 评论0 收藏0
  • ES6之"let"能替代"var"吗?

    摘要:我们将循环执行五次,每次将一个函数到数组中。只有当你理解了,才能给出正确的答案。读者提到的两个问题声明的变量不是完全不可更改。不仅如此,而且有些最新的浏览器也还没有支持。 译者按: 使用let的确会比var安全很多。 原文: Why You Shouldn’t Use ‘var’ Anymore 译者: Fundebug 为了保证可读性,本文采用意译而非直译。 我已经使用ES2015(...

    lewinlee 评论0 收藏0

发表评论

0条评论

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