2

如果我使用这段代码并编译它(高级优化)

/**@constructor*/
function MyObject() {
    this.test = 4
    this.toString = function () {return 'test object'}
}
window['MyObject'] = MyObject

我得到这个代码

window.MyObject=function(){this.test=4;this.toString=function(){return"test object"}};

有什么方法可以使用 Closure Compiler 删除 toString 函数?

4

3 回答 3

4

toString是隐式可调用的,所以除非闭包编译器可以证明结果MyObject永远不会被强制转换为字符串,否则它必须保留它。

您始终可以将其标记为显式调试代码:

this.test = 4;
if (goog.DEBUG) {
  this.toString = function () { return "test object"; };
}

然后在你的非调试版本中,编译

goog.DEBUG = false;

请参阅http://closure-library.googlecode.com/svn/docs/closure_goog_base.js.source.html

/**
 * @define {boolean} DEBUG is provided as a convenience so that debugging code
 * that should not be included in a production js_binary can be easily stripped
 * by specifying --define goog.DEBUG=false to the JSCompiler. For example, most
 * toString() methods should be declared inside an "if (goog.DEBUG)" conditional
 * because they are generally used for debugging purposes and it is difficult
 * for the JSCompiler to statically determine whether they are used.
 */
goog.DEBUG = true;
于 2010-11-12T18:49:18.633 回答
0

答案出人意料地简单。我正在研究这个并没有找到正确的答案,所以我在这里添加它。解决方案是使用 JSDoc 注释(参见https://github.com/google/closure-compiler/wiki/Annotating-JavaScript-for-the-Closure-Compiler#const-const-type):

/* @const */
const debug = false;

现在,在您的代码中的任何地方(也包括嵌套函数内部),您都可以执行以下操作:

if (debug) console.log("hello world");

或者在你的情况下使一个完整的块无效

if (debug) {
    /* your code to remove */    
}

如果您设置debug为 false,则 Closure 编译器可以将其删除,因为它知道您声明了 debug 一个常量,因此它不会更改,并且如果使用您的调试变量进行门控,则代码将永远不会被执行。

于 2020-08-14T13:04:12.070 回答
0

因为@define在模块中不起作用,所以我写了一个可以在编译之前运行的补丁。它去:

import { c } from '@artdeco/erte'
import { readFileSync, writeFileSync } from 'fs'
import { join } from 'path'

const [,,version] = process.argv

const PATH = join(__dirname, 'index.js')
let f = readFileSync(PATH, 'utf-8')

const isFree = version == '--free'

if (isFree) {
  f = f.replace("\nimport isFree from './paid'", "\n// import isFree from './paid'")
  f = f.replace("\n// import isFree from './free'", "\nimport isFree from './free'")
  console.log('Set version to %s', c('free', 'red'))
} else {
  f = f.replace("\n// import isFree from './paid'", "\nimport isFree from './paid'")
  f = f.replace("\nimport isFree from './free'", "\n// import isFree from './free'")
  console.log('Set version to %s', c('paid', 'magenta'))
}

writeFileSync(PATH, f)

用法: node ./src/version/patch --free node ./src/version/patch --paid

./src/version/index.js正在修补的实际情况:

// import isFree from './free'
import isFree from './paid'

使用“./free”:

export default true

使用“./paid”:

export default true

基于此,您可以从以下位置导出变量index.js

export const free = isFree

所以这是为了允许编译付费和免费包,但您可以扩展此代码以调整调试/生产版本。

尽管如此,这应该通过-D(@define) 来完成,但显然对于像谷歌这样的万亿美元公司来说,这非常困难。

于 2020-09-08T14:53:47.513 回答