为什么我的脚本为什么会抛出“无法重新定义属性:i”,只有缩小后才会出错?

时间:2019-02-15 16:06:57

标签: javascript webpack babeljs minify defineproperty

我有一个脚本,该脚本向对象添加方法,以便将所有内容干净地保留在一个地方。这对于未缩小的js很好,但是一旦缩小,它就会中断,我不为什么。有没有人有经验,可以指导我找到解决方案?为什么我的脚本只有缩小后才会抛出“无法重新定义属性:i”错误?

Strategy.js

const Strategy = {};

Object.defineProperty(Strategy, 'map', { value: new Map() });

Object.defineProperty(Strategy, 'registerStrategy', {
  value: function registerStrategy(fn) {
    if (fn.name) {
      this.map.set(fn.name, fn);
      return Object.defineProperty(Strategy, fn.name, { value: fn });
    }

    return false;
  },
});

export default Strategy;

strategy-1.js

import Strategy from '../strategy';

export function strategy1(param) {
    return param + ' this is strategy 1.';
}

Strategy.registerStrategy(strategy1);

strategy-2.js

import Strategy from '../strategy';

export function strategy2(param) {
    return param + ' this is strategy 2.';
}

Strategy.registerStrategy(strategy2);

webpack.config.js

import path from 'path';

const webpackConfig = {
    module: {
        rules: [
            {
                test: /\.js$/,
                use: [{
                        loader: 'babel-loader',
                        options: {
                            presets: ['env'],
                        },
                    }],
            },
        ],
    },
    mode: 'development',
    watch,
    devtool: 'source-map',
    entry: './src/js/main.js',
    output: {
        filename: 'app.js',
        path: path.resolve(__dirname, './dist/'),
    },
};

export default webpackConfig;

根据loganfsmyth的答案进行更新

Strategy.js

const Strategy = {};

Object.defineProperty(Strategy, 'map', { value: new Map() });

Object.defineProperty(Strategy, 'registerStrategy', {
  value: function registerStrategy(fnName, fn) {
    if (fnName) {
      this.map.set(fnName, fn);
      return Object.defineProperty(Strategy, fnName, {
        value: fn,
        writable: true,
        configurable: false,
      });
    }

    return false;
  },
});

Strategy.registerStrategies = (strats) => {
  Object.keys(strats).forEach((name) => {
    Strategy.registerStrategy(name, strats[name]);
  });
};

export default Strategy;

1 个答案:

答案 0 :(得分:1)

通常将函数名称用于除调试目的以外的其他事情是一个坏主意。缩小器和其他工具通常会重命名变量和函数,以实现其使代码更小的目标。这会导致Regex返回一个不同的值,因此,如果您在其他地方用硬编码对该名称进行了硬编码,而这些示例可能使minifier不能更改它,或将其更改为其他名称,则代码将中断。

对于像您这样的情况,我通常希望该功能为:

fn.name

然后可以将其概括化,并利用ES6对象速记语法:

Strategy.registerStrategy('strategy2', strategy2);

并具有该功能

Strategy.registerStrategies({ strategy2 });