code

JavaScript : Array.prototype을 확장하는 데 어떤 위험이 있습니까?

codestyles 2020. 12. 30. 08:12
반응형

JavaScript : Array.prototype을 확장하는 데 어떤 위험이 있습니까?


Google 자바 스크립트 스타일 가이드 Array.prototype . 그러나 나는 Array.prototype.filter = Array.prototype.filter || function(...) {...}그것이 존재하지 않는 브라우저에서 그것을 (및 유사한 방법) 갖는 방법으로 사용했습니다. MDN은 실제로 유사한 예를 제공합니다 .

나는 Object.prototype문제에 대해 알고 있지만 Array해시 테이블이 아닙니다.

연장 Array.prototype하는 동안 어떤 문제가 발생 하여 Google이 이에 대해 조언하게 되었습니까?


대부분의 사람들은 이것에 대한 요점을 놓쳤습니다. Polyfilling 또는 같은 표준 기능을 shimming Array.prototype.filter는 이전 버전의 브라우저에서 작동하도록하는 것입니다 내 의견에서 좋은 아이디어입니다. 싫어하는 사람들의 말을 듣지 마십시오. Mozilla는 MDN에서이를 수행하는 방법도 보여줍니다. 일반적으로 확장하지 Array.prototype않거나 다른 기본 프로토 타입에 대한 조언 은 다음 중 하나로 내려갈 수 있습니다.

  1. for..in 제대로 작동하지 않을 수 있습니다
  2. 다른 사람이 동일한 함수 이름으로 배열을 확장하려고 할 수도 있습니다.
  3. shim을 사용하더라도 모든 브라우저에서 제대로 작동하지 않을 수 있습니다.

내 답변은 다음과 같습니다.

  1. for..in일반적으로 Array에서 사용할 필요가 없습니다 . 그렇게하면 hasOwnProperty합법적인지 확인하는 데 사용할 수 있습니다 .
  2. 오직 당신 만이 당신이 그것을하고있는 유일한 사람이야 알고 원주민을 확장 또는 이 같은 표준 물건을 때 Array.prototype.filter.
  3. 이것은 성 가시고 나를 물었습니다. 이전 IE는 때때로 이러한 종류의 기능을 추가하는 데 문제가 있습니다. 사례별로 작동하는지 확인해야합니다. 나를 위해 내가 가진 문제는 Object.keysIE7 에 추가 하는 것이 었습니다 . 특정 상황에서 작동을 멈춘 것처럼 보였습니다. 귀하의 마일리지가 다를 수 있습니다.

다음 참조를 확인하십시오.

행운을 빕니다!


Nicholas Zakas의 뛰어난 기사 인 Maintainable JavaScript : Do n't modify objects you do n't modify your own : 에서 핵심 문장과 함께 글 머리 기호를 제공합니다 .

  • 신뢰성 : "간단한 설명은 엔터프라이즈 소프트웨어 제품이 유지 관리 할 수 ​​있으려면 일관되고 신뢰할 수있는 실행 환경이 필요하다는 것입니다."
  • 호환되지 않는 구현 : "소유하지 않은 객체를 수정하는 또 다른 위험은 이름 충돌 및 호환되지 않는 구현의 가능성입니다."
  • 모두가 그랬다면? : "간단히 말해서, 팀원 모두가 소유하지 않은 개체를 수정하면 이름 충돌, 호환되지 않는 구현 및 유지 관리 악몽에 빠질 것입니다."

기본적으로하지 마십시오. 프로젝트를 다른 사람이 사용하지 않고 타사 코드를 가져 오지 않더라도 그렇게하지 마십시오. 다른 사람들과 잘 어울리려고 할 때 깨기 힘든 끔찍한 습관을 갖게 될 것입니다.


Jamund Ferguson의 답변에 대한 현대적인 업데이트 :

일반적으로 Array.prototype 또는 기타 기본 프로토 타입을 확장하지 않는 것에 대한 조언은 다음 중 하나에 해당합니다.

  1. for..in이 제대로 작동하지 않을 수 있습니다.
  2. 다른 사람이 동일한 함수 이름으로 배열을 확장하려고 할 수도 있습니다.
  3. shim을 사용하더라도 모든 브라우저에서 제대로 작동하지 않을 수 있습니다.

포인트 1과 2는 이제 Symbol사용 하여 메소드를 추가 함으로써 ES6 에서 완화 할 수 있습니다 .

약간 더 서투른 호출 구조를 만들지 만 반복되지 않고 쉽게 복제 할 수없는 속성을 추가합니다.

// Any string works but a namespace may make library code easier to debug. 
var myMethod = Symbol('MyNamespace::myMethod');

Array.prototype[ myMethod ] = function(){ /* ... */ };

var arr = [];

// slightly clumsier call syntax
arr[myMethod]();

// Also works for objects
Object.prototype[ myMethod ] = function(){ /* ... */ };

장점 :

  • For..in은 예상대로 작동하지만 기호는 반복되지 않습니다.
  • 기호는 범위에 로컬이고 검색에 노력을 기울이기 때문에 메서드 이름이 충돌하지 않습니다.

단점 :


Array.prototype자신의 애플리케이션 코드를 확장 하는 것은 안전합니다 ( for .. in배열에서 사용하지 않는 한 , 비용을 지불하고 리팩토링하는 재미가 있어야합니다).

다른 사람들이 사용하려는 라이브러리의 네이티브 호스트 개체를 확장하는 것은 좋지 않습니다. 자신의 도서관에있는 다른 사람들의 환경 타락시킬 권리가 없습니다 .

하나 같은 선택 방법 뒤에이 작업을 수행 lib.extendNatives()하거나이 [].filter요구 사항으로.

네이티브 및 호스트 개체 확장


어떤 사람들은 for ... in루프를 사용하여 배열을 반복합니다. 프로토 타입에 메소드를 추가하면 루프는 해당대해 반복을 시도합니다 . 물론 이것을 위해 사용 해서는 안되지만 어쨌든 일부 사람들은 사용합니다.


프로토 타입 이이를 수행합니다. 그것은 사악합니다. 다음 스 니펫은 이렇게하면 예상치 못한 결과가 발생하는 방법을 보여줍니다.

<script language="javascript" src="https://ajax.googleapis.com/ajax/libs/prototype/1.7.0.0/prototype.js"></script>
<script language="javascript">
  a = ["not", "only", "four", "elements"];
  for (var i in a)
    document.writeln(a[i]);
</script>

결과:

not only four elements function each(iterator, context) { var index = 0; . . .

그리고 약 5000 자 이상.


poser라이브러리를 사용하여 일종의 샌드 박스를 쉽게 만들 수 있습니다 .

https://github.com/bevacqua/poser 에서 살펴보세요

var Array2 = require('poser').Array();
// <- Array

Array2.prototype.eat = function () {
  var r = this[0];
  delete this[0];
  console.log('Y U NO .shift()?');
  return r;
};

var a = new Array2(3, 5, 7);

console.log(Object.keys(Array2.prototype), Object.keys(Array.prototype))

프로토 타입을 확장하는 것은 한 번만 작동하는 트릭입니다. 당신은 어떻게 그리고 당신은과 (호환되지 않는 방식으로) 또한 그것을 수행하는 라이브러리를 사용 !


The function you are overriding could be used by the internal javascript calls and that could lead to unexpected results. Thats one of the reasons for the guideline

For example I overrode indexOf function of array and it messed up accessing array using [].


I believe this question deserves an updated ES6 answer.

ES5

First of all, as many people have already stated. Extending the native prototypes to shim or polyfill new standards or fix bugs is standard practice and not harmful. For example if a browser doesn't support the .filter method if (!Array.prototype.filter) you are free to add this functionality on your own. In-fact, the language is designed to do exactly this to manage backwards compatibility.

Now, you'd be forgving for thinking that since JavaScript object use prototypal inheritance, extending a native object like Array.prototype without interfering should be easy, but up until ES6 it's not been feasible.

Unlike objects for example, you had to rely and modifying the Array.prototype to add your own custom methods. As others have pointed out, this is bad because it pollutes the Global namespace, can interfere with other code in an unexpected way, has potential security issues, is a cardinal sin etc.

In ES5 you can try hacking this but the implementations aren't really practically useful. For more in depth information, I recommend you check out this very informative post: http://perfectionkills.com/how-ecmascript-5-still-does-not-allow-to-subclass-an-array/

You can add a method to an array, or even an array constructor but you run into issues trying to work with the native array methods that rely on the length property. Worst of all, these methods are going to return a native Array.prototype and not your shiny new sub-class array, ie: subClassArray.slice(0) instanceof subClassArray === false.

ES6

However, now with ES6 you can subclass builtins using class combined with extends Array that overcomes all these issues. It leaves the Array.prototype intact, creates a new sub-class and the array methods it inherits will be of the same sub-class! https://hacks.mozilla.org/2015/08/es6-in-depth-subclassing/

See the fiddle below for a demonstration: https://jsfiddle.net/dmq8o0q4/1/

참조 URL : https://stackoverflow.com/questions/8859828/javascript-what-dangers-are-in-extending-array-prototype

반응형