Tại sao mở rộng các đối tượng bản địa là một thực hành xấu?


136

Mỗi nhà lãnh đạo ý kiến ​​của JS đều nói rằng việc mở rộng các đối tượng bản địa là một thực tiễn tồi. Nhưng tại sao? Chúng ta có nhận được một hit perfomance? Họ có sợ rằng ai đó làm điều đó "sai cách" và thêm vô số loại vào Object, thực tế phá hủy tất cả các vòng trên bất kỳ đối tượng nào không?

Hãy TJ Holowaychuk 's should.js ví dụ. Ông cho biết thêm một getter đơn giản để Objectvà tất cả mọi thứ hoạt động tốt ( nguồn ).

Object.defineProperty(Object.prototype, 'should', {
  set: function(){},
  get: function(){
    return new Assertion(Object(this).valueOf());
  },
  configurable: true
});

Điều này thực sự có ý nghĩa. Ví dụ, người ta có thể mở rộng Array.

Array.defineProperty(Array.prototype, "remove", {
  set: function(){},
  get: function(){
    return removeArrayElement.bind(this);
  }
});
var arr = [0, 1, 2, 3, 4];
arr.remove(3);

Có bất kỳ đối số chống lại việc mở rộng các loại bản địa?


9
Bạn dự đoán điều gì sẽ xảy ra khi, sau đó, một đối tượng bản địa được thay đổi để bao gồm chức năng "loại bỏ" với các ngữ nghĩa khác nhau cho chính bạn? Bạn không kiểm soát tiêu chuẩn.
ta.speot.is

1
Đó không phải là kiểu bản địa của bạn. Đó là kiểu bản địa của mọi người.

6
"Họ có sợ rằng ai đó làm điều đó" sai cách "và thêm vô số loại vào Object, thực tế phá hủy tất cả các vòng lặp trên bất kỳ đối tượng nào không?" : Vâng. Quay trở lại những ngày khi ý kiến ​​này được hình thành, không thể tạo ra các thuộc tính không thể đếm được. Bây giờ mọi thứ có thể khác về vấn đề này, nhưng hãy tưởng tượng mọi thư viện chỉ mở rộng các đối tượng bản địa theo cách họ muốn. Có một lý do tại sao chúng tôi bắt đầu sử dụng không gian tên.
Felix Kling

5
Đối với những gì đáng để một số "nhà lãnh đạo ý kiến" ví dụ Brendan Eich nghĩ rằng việc mở rộng các nguyên mẫu bản địa là hoàn toàn tốt.
Benjamin Gruenbaum

2
Foo không nên có mặt trên toàn cầu trong những ngày này, chúng tôi đã bao gồm, các yêu cầu, phổ biến, v.v.
Jamie Pate

Câu trả lời:


127

Khi bạn mở rộng một đối tượng, bạn thay đổi hành vi của nó.

Thay đổi hành vi của một đối tượng sẽ chỉ được sử dụng bởi mã của riêng bạn là ổn. Nhưng khi bạn thay đổi hành vi của một thứ cũng được sử dụng bởi mã khác, có nguy cơ bạn sẽ phá vỡ mã khác đó.

Khi nói đến việc thêm các phương thức vào các lớp đối tượng và mảng trong javascript, nguy cơ phá vỡ một cái gì đó là rất cao, do cách javascript hoạt động. Kinh nghiệm lâu năm đã dạy tôi rằng loại công cụ này gây ra tất cả các loại lỗi khủng khiếp trong javascript.

Nếu bạn cần hành vi tùy chỉnh, tốt hơn hết là xác định lớp của riêng bạn (có thể là lớp con) thay vì thay đổi lớp gốc. Bằng cách đó bạn sẽ không phá vỡ bất cứ điều gì cả.

Khả năng thay đổi cách một lớp hoạt động mà không cần phân lớp nó là một tính năng quan trọng của bất kỳ ngôn ngữ lập trình tốt nào, nhưng nó là một thứ phải được sử dụng hiếm khi và thận trọng.


2
Vì vậy, thêm một cái gì đó như .stgringify()được coi là an toàn?
buschtoens

7
Có rất nhiều vấn đề, ví dụ điều gì xảy ra nếu một số mã khác cũng cố gắng thêm stringify()phương thức riêng của nó với hành vi khác nhau? Đó thực sự không phải là điều bạn nên làm trong lập trình hàng ngày ... không phải nếu tất cả những gì bạn muốn làm là lưu một vài ký tự mã ở đây và đó. Tốt hơn là xác định lớp hoặc hàm của riêng bạn chấp nhận bất kỳ đầu vào nào và xâu chuỗi nó. Hầu hết các trình duyệt xác định JSON.stringify(), tốt nhất sẽ là kiểm tra xem điều đó có tồn tại không và nếu không tự xác định nó.
Abhi Beckert

5
Tôi thích someError.stringify()hơn errors.stringify(someError). Nó đơn giản và hoàn toàn phù hợp với khái niệm của js. Tôi đang làm một cái gì đó đặc biệt ràng buộc với một ErrorObject nhất định.
buschtoens

1
Đối số duy nhất (nhưng tốt) vẫn còn đó là, một số lib-macro hài hước có thể bắt đầu chiếm lấy các loại của bạn và có thể can thiệp lẫn nhau. Hay còn gì nữa không?
buschtoens

4
Nếu vấn đề là bạn có thể có một vụ va chạm, bạn có thể sử dụng một mẫu mà mỗi khi bạn làm điều này, bạn luôn xác nhận rằng hàm không được xác định trước khi bạn xác định nó? Và nếu bạn luôn đặt thư viện của bên thứ ba trước mã của riêng mình, bạn sẽ có thể luôn phát hiện các xung đột đó.
Dave Cousineau

32

Không có nhược điểm có thể đo lường được, như một cú đánh hiệu suất. Ít nhất không ai đề cập đến bất kỳ. Vì vậy, đây là một câu hỏi về sở thích và kinh nghiệm cá nhân.

Đối số pro chính: Nó trông tốt hơn và trực quan hơn: cú pháp đường. Đây là một hàm cụ thể kiểu / thể hiện, vì vậy nó nên được liên kết cụ thể với kiểu / thể hiện đó.

Đối số contra chính: Mã có thể can thiệp. Nếu lib A thêm chức năng, nó có thể ghi đè chức năng của lib B. Điều này có thể phá vỡ mã rất dễ dàng.

Cả hai đều có một điểm. Khi bạn dựa vào hai thư viện thay đổi trực tiếp các loại của mình, rất có thể bạn sẽ kết thúc với mã bị hỏng vì chức năng dự kiến ​​có thể không giống nhau. Tôi hoàn toàn đồng ý về điều đó. Thư viện macro không được thao tác các kiểu gốc. Nếu không, bạn là một nhà phát triển sẽ không bao giờ biết những gì đang thực sự xảy ra đằng sau hậu trường.

Và đó là lý do tôi không thích các lib như jQuery, gạch dưới, v.v. Đừng hiểu sai ý tôi; chúng hoàn toàn được lập trình tốt và chúng hoạt động như một lá bùa, nhưng chúng rất lớn . Bạn chỉ sử dụng 10% trong số họ, và hiểu khoảng 1%.

Đó là lý do tại sao tôi thích cách tiếp cận nguyên tử , nơi bạn chỉ yêu cầu những gì bạn thực sự cần. Bằng cách này, bạn luôn biết những gì xảy ra. Các thư viện vi mô chỉ làm những gì bạn muốn họ làm, vì vậy họ sẽ không can thiệp. Trong bối cảnh có người dùng cuối biết các tính năng nào được thêm vào, việc mở rộng các kiểu gốc có thể được coi là an toàn.

TL; DR Khi nghi ngờ, không mở rộng các loại bản địa. Chỉ mở rộng loại bản địa nếu bạn chắc chắn 100%, rằng người dùng cuối sẽ biết và muốn hành vi đó. Trong mọi trường hợp, thao tác các chức năng hiện có của một kiểu bản địa, vì nó sẽ phá vỡ giao diện hiện có.

Nếu bạn quyết định mở rộng loại, sử dụng Object.defineProperty(obj, prop, desc); nếu bạn không thể , hãy sử dụng loại prototype.


Ban đầu tôi đã đưa ra câu hỏi này vì tôi muốn Errors có thể gửi được qua JSON. Vì vậy, tôi cần một cách để xâu chuỗi chúng. error.stringify()cảm thấy cách tốt hơn errorlib.stringify(error); như cấu trúc thứ hai cho thấy, tôi đang hoạt động errorlibchứ không phải trên errorchính nó.


Tôi cởi mở về những ý kiến ​​thêm về điều này.
buschtoens

4
Bạn đang ám chỉ rằng jQuery và gạch dưới mở rộng các đối tượng bản địa? Họ không. Vì vậy, nếu bạn tránh chúng vì lý do đó, bạn đã nhầm.
JLRishe

1
Đây là một câu hỏi mà tôi tin rằng đã bỏ lỡ trong cuộc tranh luận rằng việc mở rộng các đối tượng bản địa bằng lib A có thể xung đột với lib B: Tại sao bạn có hai thư viện giống nhau về bản chất hoặc có bản chất rộng đến mức có thể xảy ra xung đột này? Tức là tôi chọn lodash hoặc gạch dưới không phải cả hai. Cảnh quan thư viện hiện tại của chúng tôi trong javascript đã quá bão hòa và các nhà phát triển (nói chung) trở nên bất cẩn trong việc thêm chúng đến nỗi chúng tôi cuối cùng tránh các thực tiễn tốt nhất để xoa dịu Lãnh chúa Lib của chúng tôi
micahblu

2
@micahblu - một thư viện có thể quyết định sửa đổi một đối tượng tiêu chuẩn chỉ để thuận tiện cho việc lập trình nội bộ của chính nó (đó thường là lý do tại sao mọi người muốn làm điều này). Vì vậy, xung đột này không thể tránh được chỉ vì bạn sẽ không sử dụng hai thư viện có cùng chức năng.
jfriend00

1
Bạn cũng có thể (kể từ es2015) tạo một lớp mới mở rộng một lớp hiện có và sử dụng lớp đó trong mã của riêng bạn. vì vậy nếu MyError extends Errornó có thể có một stringifyphương thức mà không va chạm với các lớp con khác. Bạn vẫn phải xử lý các lỗi không được tạo bởi mã của riêng bạn, vì vậy nó có thể ít hữu ích Errorhơn so với các lỗi khác.
ShadSterling

16

Theo tôi, đó là một thực tế tồi. Lý do chính là hội nhập. Trích dẫn tài liệu nên.js:

OMG IT EXTENDS MỤC TIÊU ???!?! @ Vâng, đúng vậy, với một getter duy nhất, và không nó sẽ không phá vỡ mã của bạn

Vâng, làm thế nào tác giả có thể biết? Điều gì xảy ra nếu khung mô phỏng của tôi không giống nhau? Điều gì sẽ xảy ra nếu lời hứa của tôi không giống nhau?

Nếu bạn đang làm điều đó trong dự án của riêng bạn thì tốt thôi. Nhưng đối với một thư viện, thì đó là một thiết kế tồi. Underscore.js là một ví dụ về điều được thực hiện đúng cách:

var arr = [];
_(arr).flatten()
// or: _.flatten(arr)
// NOT: arr.flatten()

2
Tôi chắc chắn rằng phản hồi của TJ sẽ không sử dụng những lời hứa hoặc chế giễu đó: x
Jim Schubert

Các _(arr).flatten()ví dụ thực sự thuyết phục tôi không mở rộng đối tượng người bản xứ. Lý do cá nhân của tôi để làm như vậy là hoàn toàn cú pháp. Nhưng điều này thỏa mãn cảm giác thẩm mỹ của tôi :) Ngay cả khi sử dụng một số tên hàm thông thường hơn như foo(native).coolStuff()chuyển đổi nó thành một số đối tượng "mở rộng" trông rất tuyệt về mặt cú pháp. Vì vậy, cảm ơn vì điều đó!
vd: 27/10/18

16

Nếu bạn xem xét nó trên cơ sở từng trường hợp, có lẽ một số triển khai được chấp nhận.

String.prototype.slice = function slice( me ){
  return me;
}; // Definite risk.

Ghi đè các phương thức đã tạo tạo ra nhiều vấn đề hơn giải quyết, đó là lý do tại sao nó thường được nêu, trong nhiều ngôn ngữ lập trình, để tránh thực hành này. Làm thế nào là Dev để biết chức năng đã được thay đổi?

String.prototype.capitalize = function capitalize(){
  return this.charAt(0).toUpperCase() + this.slice(1);
}; // A little less risk.

Trong trường hợp này, chúng tôi không ghi đè bất kỳ phương thức JS cốt lõi nào đã biết, nhưng chúng tôi đang mở rộng Chuỗi. Một đối số trong bài viết này đã đề cập đến việc nhà phát triển mới biết liệu phương thức này là một phần của JS cốt lõi hay tìm tài liệu ở đâu? Điều gì sẽ xảy ra nếu đối tượng Chuỗi JS cốt lõi có được một phương thức có tên là hoa ?

Điều gì sẽ xảy ra nếu thay vì thêm tên có thể xung đột với các thư viện khác, bạn đã sử dụng công cụ sửa đổi cụ thể cho công ty / ứng dụng mà tất cả các nhà phát triển có thể hiểu được?

String.prototype.weCapitalize = function weCapitalize(){
  return this.charAt(0).toUpperCase() + this.slice(1);
}; // marginal risk.

var myString = "hello to you.";
myString.weCapitalize();
// => Hello to you.

Nếu bạn tiếp tục mở rộng các đối tượng khác, tất cả các nhà phát triển sẽ gặp họ trong tự nhiên với (trong trường hợp này) , chúng tôi sẽ thông báo cho họ rằng đó là tiện ích mở rộng dành riêng cho công ty / ứng dụng.

Điều này không loại bỏ va chạm tên, nhưng làm giảm khả năng. Nếu bạn xác định rằng việc mở rộng các đối tượng JS cốt lõi là dành cho bạn và / hoặc nhóm của bạn, có lẽ đây là dành cho bạn.


7

Mở rộng các nguyên mẫu của tích hợp thực sự là một ý tưởng tồi. Tuy nhiên, ES2015 đã giới thiệu một kỹ thuật mới có thể được sử dụng để có được hành vi mong muốn:

Sử dụng WeakMaps để liên kết các loại với các nguyên mẫu tích hợp

Việc thực hiện sau đây mở rộng Numbervà các Arraynguyên mẫu mà không chạm vào chúng:

// new types

const AddMonoid = {
  empty: () => 0,
  concat: (x, y) => x + y,
};

const ArrayMonoid = {
  empty: () => [],
  concat: (acc, x) => acc.concat(x),
};

const ArrayFold = {
  reduce: xs => xs.reduce(
   type(xs[0]).monoid.concat,
   type(xs[0]).monoid.empty()
)};


// the WeakMap that associates types to prototpyes

types = new WeakMap();

types.set(Number.prototype, {
  monoid: AddMonoid
});

types.set(Array.prototype, {
  monoid: ArrayMonoid,
  fold: ArrayFold
});


// auxiliary helpers to apply functions of the extended prototypes

const genericType = map => o => map.get(o.constructor.prototype);
const type = genericType(types);


// mock data

xs = [1,2,3,4,5];
ys = [[1],[2],[3],[4],[5]];


// and run

console.log("reducing an Array of Numbers:", ArrayFold.reduce(xs) );
console.log("reducing an Array of Arrays:", ArrayFold.reduce(ys) );
console.log("built-ins are unmodified:", Array.prototype.empty);

Như bạn có thể thấy các nguyên mẫu nguyên thủy có thể được mở rộng bằng kỹ thuật này. Nó sử dụng cấu trúc bản đồ và Objectdanh tính để liên kết các loại với các nguyên mẫu tích hợp.

Ví dụ của tôi cho phép một reducehàm chỉ mong đợi một Arrayđối số duy nhất của nó, bởi vì nó có thể trích xuất thông tin làm thế nào để tạo một bộ tích lũy trống và cách nối các phần tử với bộ tích lũy này từ chính các phần tử của mảng.

Xin lưu ý rằng tôi có thể đã sử dụng Maploại bình thường , vì các tham chiếu yếu không có ý nghĩa khi chúng chỉ đại diện cho các nguyên mẫu tích hợp, không bao giờ được thu gom rác. Tuy nhiên, WeakMapkhông thể lặp lại và không thể kiểm tra trừ khi bạn có khóa đúng. Đây là một tính năng mong muốn, vì tôi muốn tránh mọi hình thức phản chiếu kiểu.


Đây là một cách sử dụng tuyệt vời của WeakMap. Hãy cẩn thận với điều đó xs[0]trên mảng trống tho. type(undefined).monoid ...
Cảm ơn bạn

@naomik Tôi biết - xem câu hỏi mới nhất của tôi đoạn mã thứ 2.

Làm thế nào tiêu chuẩn là hỗ trợ cho @ftor này?
onassar

5
-1; điểm của bất kỳ điều này là gì? Bạn chỉ đang tạo một loại ánh xạ từ điển toàn cầu riêng biệt cho các phương thức và sau đó tìm kiếm rõ ràng các phương thức trong từ điển đó theo loại. Kết quả là, bạn mất hỗ trợ cho thừa kế (một phương thức "được thêm vào" Object.prototypetheo cách này không thể được gọi trên Array) và cú pháp dài hơn / xấu hơn đáng kể so với khi bạn thực sự mở rộng một nguyên mẫu. Hầu như luôn luôn đơn giản hơn khi chỉ tạo các lớp tiện ích bằng các phương thức tĩnh; lợi thế duy nhất của phương pháp này là một số hỗ trợ hạn chế cho đa hình.
Đánh dấu Amery

4
@MarkAmery Này bạn, bạn không hiểu. Tôi không mất quyền thừa kế nhưng hãy loại bỏ nó. Kế thừa là những năm 80, bạn nên quên nó đi. Toàn bộ quan điểm của vụ hack này là bắt chước các lớp loại, đơn giản là đặt các hàm quá tải. Có một lời chỉ trích hợp pháp mặc dù: Có hữu ích khi bắt chước các lớp loại trong Javascript không? Không, không phải vậy. Thay vì sử dụng một ngôn ngữ đánh máy hỗ trợ họ nguyên bản. Tôi khá chắc chắn đây là những gì bạn có ý nghĩa.

7

Thêm một lý do tại sao bạn không nên mở rộng Đối tượng gốc:

Chúng tôi sử dụng Magento sử dụng nguyên mẫu và mở rộng rất nhiều thứ trên các Đối tượng gốc. Điều này hoạt động tốt cho đến khi bạn quyết định nhận các tính năng mới và đó là nơi những rắc rối lớn bắt đầu.

Chúng tôi đã giới thiệu Webcomponents trên một trong các trang của mình, vì vậy, các thành phần web-lite.js quyết định thay thế toàn bộ Đối tượng sự kiện (nguyên gốc) trong IE (tại sao?). Điều này tất nhiên phá vỡ nguyên mẫu.js mà lần lượt phá vỡ Magento. (cho đến khi bạn tìm thấy vấn đề, bạn có thể đầu tư rất nhiều giờ để truy tìm lại)

Nếu bạn thích rắc rối, hãy tiếp tục làm điều đó!


4

Tôi có thể thấy ba lý do để không làm điều này ( ít nhất là trong một ứng dụng ), chỉ có hai lý do trong các câu trả lời hiện có ở đây:

  1. Nếu bạn làm sai, bạn sẽ vô tình thêm một thuộc tính vô số vào tất cả các đối tượng thuộc loại mở rộng. Dễ dàng làm việc xung quanh bằng cách sử dụng Object.defineProperty, tạo ra các thuộc tính không thể đếm được theo mặc định.
  2. Bạn có thể gây ra xung đột với thư viện mà bạn đang sử dụng. Có thể tránh được với sự siêng năng; chỉ cần kiểm tra những phương thức mà thư viện bạn sử dụng xác định trước khi thêm một cái gì đó vào nguyên mẫu, kiểm tra ghi chú phát hành khi nâng cấp và kiểm tra ứng dụng của bạn.
  3. Bạn có thể gây ra xung đột với phiên bản tương lai của môi trường JavaScript gốc.

Điểm 3 được cho là quan trọng nhất. Bạn có thể đảm bảo, thông qua thử nghiệm, các tiện ích mở rộng nguyên mẫu của bạn không gây ra bất kỳ xung đột nào với các thư viện bạn sử dụng, vì bạn quyết định thư viện nào bạn sử dụng. Điều tương tự cũng không đúng với các đối tượng gốc, giả sử rằng mã của bạn chạy trong trình duyệt. Nếu bạn xác định Array.prototype.swizzle(foo, bar)ngày hôm nay và ngày mai Google sẽ thêm Array.prototype.swizzle(bar, foo)vào Chrome, bạn sẽ có khả năng kết thúc với một số đồng nghiệp bối rối, người tự hỏi tại sao .swizzlehành vi của họ dường như không khớp với những gì được ghi lại trên MDN.

(Xem thêm câu chuyện về cách các mootools nghịch ngợm với các nguyên mẫu mà họ không sở hữu đã buộc phải đổi tên phương thức ES6 để tránh phá vỡ web .)

Điều này có thể tránh được bằng cách sử dụng tiền tố dành riêng cho ứng dụng cho các phương thức được thêm vào đối tượng gốc (ví dụ: xác định Array.prototype.myappSwizzlethay vì Array.prototype.swizzle), nhưng đó là loại xấu xí; nó cũng có thể giải quyết được bằng cách sử dụng các chức năng tiện ích độc lập thay vì tăng các nguyên mẫu.


2

Perf cũng là một lý do. Đôi khi bạn có thể cần phải lặp qua các phím. có nhiều hướng khác nhau để làm điều đó

for (let key in object) { ... }
for (let key in object) { if (object.hasOwnProperty(key) { ... } }
for (let key of Object.keys(object)) { ... }

Tôi thường sử dụng for of Object.keys()vì nó làm đúng và tương đối ngắn gọn, không cần thêm kiểm tra.

Nhưng, nó chậm hơn nhiều .

kết quả hoàn hảo so với kết quả hoàn hảo

Chỉ cần đoán lý do Object.keyslà chậm là rõ ràng, Object.keys()phải phân bổ. Trong thực tế AFAIK, nó phải phân bổ một bản sao của tất cả các khóa kể từ đó.

  const before = Object.keys(object);
  object.newProp = true;
  const after = Object.keys(object);

  before.join('') !== after.join('')

Có thể công cụ JS có thể sử dụng một số loại cấu trúc khóa bất biến để Object.keys(object)trả về một tham chiếu thứ gì đó lặp lại trên các khóa bất biến và object.newProptạo ra một đối tượng khóa bất biến hoàn toàn mới nhưng dù sao, nó rõ ràng chậm hơn tới 15 lần

Ngay cả việc kiểm tra hasOwnPropertycũng chậm hơn tới 2 lần.

Điểm quan trọng của tất cả đó là nếu bạn có mã nhạy cảm hoàn hảo và cần lặp lại các khóa thì bạn muốn có thể sử dụng for inmà không phải gọi hasOwnProperty. Bạn chỉ có thể làm điều này nếu bạn chưa sửa đổiObject.prototype

lưu ý rằng nếu bạn sử dụng Object.definePropertyđể sửa đổi nguyên mẫu nếu những thứ bạn thêm vào không thể đếm được thì chúng sẽ không ảnh hưởng đến hành vi của JavaScript trong các trường hợp trên. Thật không may, ít nhất là trong Chrome 83, chúng ảnh hưởng đến hiệu suất.

nhập mô tả hình ảnh ở đây

Tôi đã thêm 3000 thuộc tính không thể đếm được chỉ để cố gắng buộc bất kỳ vấn đề hoàn hảo nào xuất hiện. Chỉ với 30 thuộc tính, các thử nghiệm đã quá gần để biết liệu có bất kỳ tác động hoàn hảo nào hay không.

https://jsperf.com/does-adding-non-enumerable-properies-affect-perf

Firefox 77 và Safari 13.1 cho thấy không có sự khác biệt về sự hoàn hảo giữa các lớp Augmented và Unaugished có thể v8 sẽ được sửa trong lĩnh vực này và bạn có thể bỏ qua các vấn đề hoàn hảo.

Nhưng, hãy để tôi cũng thêm đó là câu chuyện củaArray.prototype.smoosh . Phiên bản ngắn là Mootools, một thư viện phổ biến, được tạo riêng Array.prototype.flatten. Khi ủy ban tiêu chuẩn cố gắng thêm một người bản địa, Array.prototype.flattenhọ đã tìm thấy không thể phá vỡ nhiều trang web. Các nhà phát triển đã phát hiện ra việc phá vỡ đề nghị đặt tên phương thức es5 smooshlà một trò đùa nhưng mọi người hoảng hốt không hiểu đó là một trò đùa. Họ giải quyết flatthay vìflatten

Đạo đức của câu chuyện là bạn không nên mở rộng các đối tượng bản địa. Nếu bạn làm như vậy, bạn có thể gặp phải vấn đề tương tự về việc phá vỡ nội dung của mình và trừ khi thư viện cụ thể của bạn trở nên phổ biến như MooTools, các nhà cung cấp trình duyệt không có khả năng giải quyết vấn đề bạn gây ra. Nếu thư viện của bạn trở nên phổ biến, đó sẽ là một ý nghĩa để buộc mọi người khác giải quyết vấn đề bạn gây ra. Vì vậy, xin vui lòng không mở rộng đối tượng bản địa


Đợi, hasOwnPropertycho bạn biết liệu tài sản là trong đối tượng hoặc nguyên mẫu. Nhưng for invòng lặp chỉ giúp bạn có được vô số thuộc tính. Tôi vừa thử điều này: Thêm một thuộc tính không thể đếm được vào nguyên mẫu Array và nó sẽ không hiển thị trong vòng lặp. Không cần phải sửa đổi nguyên mẫu cho vòng lặp đơn giản nhất để làm việc.
ygoe

Nhưng đó vẫn là một thực tiễn tồi vì những lý do khác;)
gman
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.