Function과 Class에는 read-only nme property가 존재한다.
function.name 하면 함수 이름을 반환해준다.
function test() {}
console.log(test.name); // test
객체로 생성된 object도 constructor.name을 사용할 수 있다.
class ClassTest {}
let a = new ClassTest();
console.log(a.constructor.name); // ClassTest
webpack으로 난독화(uglify)와 압축(minify)되면서 name이 production mode에선 유지되지 않았다.
의미가 없는 e나 i출력되거나, 클래스도 여러개가 하나로 합쳐지면서 코드 사용이 어려워지는 현상이었고 관련 워닝이 mdn에 기록되어 있었다.
설명된 예시를 좀 더 해석해보면 이렇다.
아래 코드처럼 원래는 Foo로 함수를 생성하였다고 한다.
function Foo() {};
let foo = new Foo();
if (foo.constructor.name === 'Foo') {
console.log("'foo' is an instance of 'Foo'");
} else {
console.log('Oops!');
}
그러나 압축되면서 이런 방식으로 변경이 되면서 코드가 기존 로직으로 돌아가지 않는 것이다.
function a() {};
let b = new a();
if (b.constructor.name === 'Foo') {
console.log("'foo' is an instance of 'Foo'");
} else {
console.log('Oops!');
}
webpack 설정 수정
keep_fnames, keep_classnames를 유지하는 옵션이 있다.
다만 이렇게 했을 때 압축과 난독화의 장점을 가지고 가지 못하니, 보안성과 파일 사이즈가 늘어날 것이다.
선언 확장과 eslint
global declare로 선언 확장해서 deprecated 표시를 해서 lint에 걸리게 한다는 글을 발견했다. typescript 라면 유용할 것으로 보인다.
declare global {
interface Function {
/** @deprecated Don't use this, think about the children!*/
readonly name: string;
}
}
"rules": {
"deprecation": true
}
declare global {
interface Function {
/**
* Returns the name of the function. Function names are read-only and can not be changed.
* @deprecated no recommended our feature due to wepback minify/uglify features
*/
readonly name: string;
}
}
export {};
typescript랑만 사용 가능하다.
npm i -D eslint-plugin-deprecation
eslint 에 plugin을 추가하고 rule도 설정하였다. rule은 strict하게 error로 가져가려고 한다.
...
plugins: ['@typescript-eslint', 'react-hooks', 'deprecation'],
...
parserOptions: {
ecmaVersion: 2020,
sourceType: 'module',
project: './tsconfig.json',
},
...
rules: {
...
'deprecation/deprecation': 'error',
임의로 추가한 deprecated 선언도 잘 출력되는 것을 보았다
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/name
https://medium.com/@eransakal/fix-javascript-issues-with-function-name-7079742f1a05
https://stackoverflow.com/questions/64876188/typescript-prevent-use-of-name-to-get-function-class-name