क्यों देशी वस्तुओं को एक बुरी प्रथा का विस्तार किया जा रहा है


136

जेएस राय के हर नेता का कहना है कि मूल वस्तुओं का विस्तार करना एक बुरा व्यवहार है। पर क्यों? हम एक परिपूर्णता हिट मिलता है? क्या उन्हें डर है कि कोई इसे "गलत तरीके से" करता है, और Objectकिसी भी वस्तु पर व्यावहारिक रूप से सभी छोरों को नष्ट करने के लिए अनगिनत प्रकार जोड़ता है ?

लो टीजे Holowaychuk के should.js उदाहरण के लिए। उन्होंने कहा कि एक साधारण गेटर कहते हैं करने के लिए Objectऔर सब कुछ ठीक (काम करता है स्रोत )।

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

यह वास्तव में समझ में आता है। उदाहरण के लिए, कोई भी विस्तार कर सकता है Array

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

क्या देशी प्रकारों के विस्तार के खिलाफ कोई तर्क हैं?


9
जब आप, बाद में, एक मूल वस्तु को अपने स्वयं के लिए अलग-अलग शब्दार्थों के साथ "हटाने" फ़ंक्शन को शामिल करने के लिए बदल जाते हैं, तो क्या होने की उम्मीद है? आप मानक को नियंत्रित नहीं करते हैं।
ta.speot.is

1
यह आपका मूल प्रकार नहीं है। यह हर किसी का मूल प्रकार है।

6
"क्या उन्हें डर है कि कोई इसे" गलत तरीके से "करता है, और किसी भी वस्तु पर व्यावहारिक रूप से सभी छोरों को नष्ट करने के लिए, अनगिनत प्रकार जोड़ता है?" : हां। उन दिनों में जब इस राय का गठन किया गया था, तब गैर-गुणकारी गुणों को बनाना असंभव था। अब इस संबंध में चीजें अलग हो सकती हैं, लेकिन हर पुस्तकालय की कल्पना करें कि वे मूल वस्तुओं का विस्तार कैसे करें। ऐसा कोई कारण है कि हमने नामस्थानों का उपयोग करना शुरू कर दिया है।
फेलिक्स क्लिंग

5
उदाहरण के लिए कुछ "राय नेताओं" के लायक है ब्रेंडन ईच को लगता है कि यह मूल प्रोटोटाइप का विस्तार करने के लिए बिल्कुल ठीक है।
बेंजामिन ग्रुएनबाम

2
फू इन दिनों वैश्विक नहीं होना चाहिए, हमारे पास शामिल हैं, आवश्यकताएं, कॉमनज आदि।
जेमी

जवाबों:


127

जब आप किसी ऑब्जेक्ट का विस्तार करते हैं, तो आप उसके व्यवहार को बदलते हैं।

किसी वस्तु का व्यवहार बदलना जो केवल आपके ही कोड द्वारा उपयोग किया जाएगा ठीक है। लेकिन जब आप किसी ऐसी चीज के व्यवहार को बदलते हैं जिसका उपयोग अन्य कोड द्वारा भी किया जाता है तो एक जोखिम होता है कि आप उस अन्य कोड को तोड़ देंगे।

जब यह जावास्क्रिप्ट में ऑब्जेक्ट और एरे क्लास के तरीकों को जोड़ते हैं, तो जावास्क्रिप्ट कैसे काम करता है, इसके कारण कुछ को तोड़ने का जोखिम बहुत अधिक है। लंबे समय के अनुभव ने मुझे सिखाया है कि इस तरह के सामान के कारण जावास्क्रिप्ट में सभी प्रकार के भयानक कीड़े होते हैं।

यदि आपको कस्टम व्यवहार की आवश्यकता है, तो देशी को बदलने के बजाय अपनी खुद की कक्षा (शायद एक उपवर्ग) को परिभाषित करना बेहतर है। इस तरह आप कुछ भी नहीं तोड़ेंगे।

यह समझने की क्षमता है कि किसी वर्ग को उप-वर्ग के बिना कैसे काम करता है यह किसी भी अच्छी प्रोग्रामिंग भाषा की एक महत्वपूर्ण विशेषता है, लेकिन यह एक है जिसे शायद ही कभी और सावधानी के साथ उपयोग किया जाना चाहिए।


2
तो ऐसा कुछ जोड़ना .stgringify()सुरक्षित माना जाएगा?
बुचटोन्स

7
बहुत सारे मुद्दे हैं, उदाहरण के लिए अगर कुछ अन्य कोड भी stringify()अलग-अलग व्यवहार के साथ अपने स्वयं के तरीके को जोड़ने की कोशिश करता है तो क्या होता है? यह वास्तव में ऐसा कुछ नहीं है जिसे आपको रोज़मर्रा की प्रोग्रामिंग में करना चाहिए ... यदि आप करना चाहते हैं तो कोड के कुछ वर्णों को इधर-उधर न करें। अपने स्वयं के वर्ग या फ़ंक्शन को परिभाषित करने के लिए बेहतर है जो किसी भी इनपुट को स्वीकार करता है और इसे स्ट्रिंग करता है। अधिकांश ब्राउज़र परिभाषित करते हैं JSON.stringify(), सबसे अच्छा यह होगा कि यदि मौजूद है, और यदि यह स्वयं को परिभाषित नहीं करता है, तो जांच करें।
अभि बेकर्ट

5
मैं पसंद someError.stringify()से अधिक errors.stringify(someError)। यह सीधा है और पूरी तरह से जेएस की अवधारणा के अनुरूप है। मैं कुछ ऐसा कर रहा हूं जो विशेष रूप से एक निश्चित ErrorObject के लिए बाध्य है।
बसकॉटेन्स

1
एकमात्र (लेकिन अच्छा) तर्क जो बना हुआ है, वह यह है कि कुछ विनम्र मैक्रो-लिब आपके प्रकारों को लेना शुरू कर सकते हैं और एक दूसरे के साथ हस्तक्षेप कर सकते हैं। या कुछ और भी है?
3

4
यदि समस्या यह है कि आपके पास टक्कर हो सकती है, तो क्या आप एक पैटर्न का उपयोग कर सकते हैं जहां हर बार आपने ऐसा किया था, आप हमेशा पुष्टि करते हैं कि फ़ंक्शन परिभाषित करने से पहले अपरिभाषित है? और यदि आप हमेशा अपने स्वयं के कोड से पहले तीसरे पक्ष के पुस्तकालय रखते हैं, तो आपको हमेशा इस तरह के टकरावों का पता लगाने में सक्षम होना चाहिए।
डेव कजिनो

32

प्रदर्शन हिट की तरह कोई औसत दर्जे की कमी नहीं है। कम से कम किसी ने कोई जिक्र नहीं किया। तो यह व्यक्तिगत पसंद और अनुभवों का सवाल है।

मुख्य समर्थक तर्क: यह बेहतर दिखता है और अधिक सहज है: वाक्यविन्यास चीनी। यह एक प्रकार / आवृत्ति विशिष्ट कार्य है, इसलिए इसे विशेष रूप से उस प्रकार / आवृत्ति से बंधा होना चाहिए।

मुख्य गर्भनिरोधक तर्क: कोड हस्तक्षेप कर सकता है। यदि lib A फ़ंक्शन जोड़ता है, तो यह lib B के फ़ंक्शन को अधिलेखित कर सकता है। इससे कोड बहुत आसानी से टूट सकता है।

दोनों में एक बिंदु है। जब आप दो पुस्तकालयों पर भरोसा करते हैं जो सीधे आपके प्रकारों को बदलते हैं, तो आप सबसे अधिक संभावना टूटे हुए कोड के साथ समाप्त करेंगे क्योंकि अपेक्षित कार्यक्षमता शायद समान नहीं है। मैं उस पर पूरी तरह सहमत हूं। मैक्रो-लाइब्रेरीज़ को मूल प्रकारों में हेरफेर नहीं करना चाहिए। अन्यथा आप एक डेवलपर के रूप में कभी नहीं जान पाएंगे कि वास्तव में पर्दे के पीछे क्या चल रहा है।

और यही कारण है कि मुझे jQuery, अंडरस्कोर इत्यादि जैसे लिबास नापसंद हैं, मुझे गलत मत समझो; वे पूरी तरह से क्रमादेशित हैं और वे एक आकर्षण की तरह काम करते हैं, लेकिन वे बड़े हैं । आप उनमें से केवल 10% का उपयोग करते हैं, और 1% के बारे में समझते हैं।

इसलिए मैं एक परमाणु दृष्टिकोण पसंद करता हूं , जहां आपको केवल वही चाहिए जो आपको वास्तव में चाहिए। इस तरह, आप हमेशा जानते हैं कि क्या होता है। माइक्रो-लाइब्रेरी केवल वही करते हैं जो आप उन्हें करना चाहते हैं, इसलिए वे हस्तक्षेप नहीं करेंगे। अंत उपयोगकर्ता होने के संदर्भ में यह जानते हुए कि कौन सी विशेषताएं जोड़ी जाती हैं, देशी प्रकारों को विस्तारित करना सुरक्षित माना जा सकता है।

टीएल, डॉ। जब संदेह में, देशी प्रकार का विस्तार न करें। केवल एक देशी प्रकार का विस्तार करें यदि आप 100% सुनिश्चित हैं, कि अंतिम उपयोगकर्ता को उस व्यवहार के बारे में पता चल जाएगा और चाहते हैं। किसी भी मामले में एक देशी प्रकार के मौजूदा कार्यों में हेरफेर नहीं करता है, क्योंकि यह मौजूदा इंटरफ़ेस को तोड़ देगा।

यदि आप प्रकार का विस्तार करने का निर्णय लेते हैं, तो उपयोग करें Object.defineProperty(obj, prop, desc); यदि आप नहीं कर सकते हैं , तो टाइप का उपयोग करें prototype


मैं मूल रूप से इस सवाल के साथ आया था क्योंकि मैं ErrorJSON के माध्यम से भेजने योग्य होना चाहता था । इसलिए, मुझे उन्हें संशोधित करने के लिए एक तरीका चाहिए था। error.stringify()बेहतर तरीके से महसूस किया errorlib.stringify(error); जैसा कि दूसरे निर्माण से पता चलता है, मैं खुद errorlibपर काम कर रहा हूं न कि errorखुद पर ।


मैं इस पर आगे की राय पर खुला हूं।
बसचोटेन्स

4
क्या आप अनुमान लगा रहे हैं कि jQuery और अंडरस्कोर देशी वस्तुओं का विस्तार करता है? वे नहीं करते। इसलिए यदि आप उन्हें इस कारण से बचा रहे हैं, तो आप गलत हैं।
JLRishe

1
यहाँ एक सवाल है कि मेरा मानना ​​है कि इस तर्क में चूक हुई है कि मूल वस्तुओं को लिबास ए के साथ जोड़ा जा सकता है, बी के साथ संघर्ष हो सकता है: आपके पास दो पुस्तकालय क्यों होंगे जो या तो प्रकृति में समान हैं या प्रकृति में इतने व्यापक हैं कि यह संघर्ष संभव है? यानी मैं या तो लॉश को चुनता हूं या अंडरस्कोर दोनों को नहीं। जावास्क्रिप्ट में हमारा वर्तमान लाइब्रेरई परिदृश्य बहुत अधिक संतृप्त है और डेवलपर्स (सामान्य रूप में) उन्हें जोड़ने में इतने लापरवाह हो जाते हैं कि हम अपने लीब लॉर्ड्स से
अपील

2
@micahblu - एक पुस्तकालय अपनी आंतरिक प्रोग्रामिंग की सुविधा के लिए एक मानक वस्तु को संशोधित करने का निर्णय ले सकता है (यही कारण है कि लोग ऐसा करना चाहते हैं)। इसलिए, इस संघर्ष को सिर्फ इसलिए टाला नहीं गया क्योंकि आप एक ही फ़ंक्शन वाले दो पुस्तकालयों का उपयोग नहीं करेंगे।
jfriend00

1
आप (es2015 के रूप में) एक नया वर्ग बना सकते हैं जो एक मौजूदा वर्ग का विस्तार करता है, और इसे अपने कोड में उपयोग करें। तो अगर MyError extends Errorयह stringifyअन्य उपवर्गों से टकराए बिना एक विधि हो सकती है । आपको अभी भी अपने कोड द्वारा उत्पन्न त्रुटियों को नहीं संभालना है, इसलिए यह Errorदूसरों की तुलना में कम उपयोगी हो सकता है।
ShadSterling

16

मेरी राय में, यह एक बुरा अभ्यास है। इसकी बड़ी वजह एकीकरण है। उद्धरण देना चाहिए .js डॉक्स:

OMG IT EXTENDS OBJECT ???! @! हाँ, हाँ, यह करता है, एक ही गेटवे के साथ, और नहीं यह आपके कोड को नहीं तोड़ेगा

भला, लेखक कैसे जान सकता है? क्या होगा अगर मेरा मजाक बनाने वाला ढांचा वही करता है? क्या होगा अगर मेरे वादे ही सही हैं?

यदि आप इसे अपने प्रोजेक्ट में कर रहे हैं तो यह ठीक है। लेकिन एक पुस्तकालय के लिए, तो यह एक बुरा डिजाइन है। Underscore.js सही तरीके से की गई चीज़ का एक उदाहरण है:

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

2
मुझे यकीन है कि टीजे की प्रतिक्रिया उन वादों या मजाकिया ढांचे का उपयोग नहीं करने के लिए होगी: एक्स
जिम स्कुबर्ट

_(arr).flatten()उदाहरण वास्तव में देशी वस्तुओं का विस्तार करने के लिए नहीं मुझे राजी कर लिया। ऐसा करने का मेरा व्यक्तिगत कारण विशुद्ध रूप से वाक्यात्मक था। लेकिन यह मेरी सौंदर्य की भावना को संतुष्ट करता है :) यहां तक ​​कि कुछ और नियमित फ़ंक्शन नाम का उपयोग करते हुए foo(native).coolStuff()इसे कुछ "विस्तारित" ऑब्जेक्ट में बदलना बहुत अच्छा लगता है। तो उसके लिए धन्यवाद!
egst

16

यदि आप इसे किसी मामले के आधार पर देखते हैं, तो शायद कुछ कार्यान्वयन स्वीकार्य हैं।

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

इस पद्धति से बचने के लिए, पहले से निर्मित विधियों में ओवरराइटिंग से अधिक समस्याएँ पैदा होती हैं, यही वजह है कि कई प्रोग्रामिंग भाषाओं में इसे आमतौर पर कहा जाता है। समारोह को बदलने के लिए देवों को कैसे जाना जाता है?

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

इस मामले में हम किसी भी ज्ञात जेएस विधि को अधिलेखित नहीं कर रहे हैं, लेकिन हम स्ट्रिंग का विस्तार कर रहे हैं। इस पोस्ट में एक तर्क का उल्लेख किया गया है कि यह जानने के लिए नए देव कैसे हैं कि क्या यह विधि कोर JS का हिस्सा है, या डॉक्स को कहां खोजना है? यदि कोर जेएस स्ट्रिंग ऑब्जेक्ट को कैपिटलाइज़ नाम की विधि प्राप्त होती है तो क्या होगा ?

क्या होगा अगर अन्य पुस्तकालयों के साथ टकराव वाले नामों को जोड़ने के बजाय, आपने एक कंपनी / ऐप विशिष्ट संशोधक का उपयोग किया जिसे सभी देवता समझ सकें?

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.

यदि आप अन्य वस्तुओं का विस्तार करना जारी रखते हैं, तो सभी देवता उनके साथ जंगली में (इस मामले में) हमारा सामना करेंगे , जो उन्हें सूचित करेगा कि यह एक कंपनी / ऐप विशिष्ट एक्सटेंशन था।

यह नाम टकराव को समाप्त नहीं करता है, लेकिन संभावना को कम करता है। यदि आप यह निर्धारित करते हैं कि विस्तारित जेएस वस्तुएं आपके और / या आपकी टीम के लिए हैं, तो शायद यह आपके लिए है।


7

बिल्ट-इन के प्रोटोटाइप का विस्तार वास्तव में एक बुरा विचार है। हालाँकि, ES2015 ने एक नई तकनीक पेश की जिसका उपयोग वांछित व्यवहार प्राप्त करने के लिए किया जा सकता है:

WeakMapअंतर्निहित प्रोटोटाइप के साथ सहयोगी प्रकारों का उपयोग करना

निम्नलिखित कार्यान्वयन सभी को छूने के बिना Numberऔर Arrayप्रोटोटाइप का विस्तार करता है :

// 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);

जैसा कि आप देख सकते हैं कि इस तकनीक द्वारा आदिम प्रोटोटाइप को भी बढ़ाया जा सकता है। यह Objectबिल्ट-इन प्रोटोटाइप के साथ एक प्रकार की संरचना और पहचान का उपयोग करता है ।

मेरा उदाहरण एक reduceफ़ंक्शन को सक्षम करता है जो केवल Arrayअपने एकल तर्क के रूप में अपेक्षा करता है, क्योंकि यह जानकारी को निकाल सकता है कि एक खाली संचयक कैसे बनाया जाए और कैसे इस संचायक के साथ तत्वों को ऐरे के तत्वों से अलग किया जाए।

कृपया ध्यान दें कि मैं सामान्य Mapप्रकार का उपयोग कर सकता था , क्योंकि कमजोर संदर्भों का कोई मतलब नहीं है जब वे केवल निर्मित प्रोटोटाइप का प्रतिनिधित्व करते हैं, जो कभी भी कचरा एकत्र नहीं होते हैं। हालाँकि, WeakMapजब तक आपके पास सही कुंजी न हो, तब तक यह चलने योग्य नहीं है और इसका निरीक्षण नहीं किया जा सकता है। यह एक वांछित विशेषता है, क्योंकि मैं किसी भी प्रकार के प्रतिबिंब से बचना चाहता हूं।


यह WeakMap का एक अच्छा उपयोग है। xs[0]खाली arrays के साथ उस पर सावधान रहें । type(undefined).monoid ...
धन्यवाद

@naomik मुझे पता है - मेरे नवीनतम प्रश्न को दूसरा कोड स्निपेट देखें।

इस @ आफत के लिए समर्थन कितना मानक है?
onassar

5
-1; इसमें से किसी का क्या मतलब है? आप केवल विधियों के लिए एक अलग वैश्विक शब्दकोश मानचित्रण प्रकार बना रहे हैं, और फिर स्पष्ट रूप से उस शब्दकोश में विधियों को देख रहे हैं। परिणामस्वरूप, आप इनहेरिटेंस के लिए समर्थन खो देते हैं ( Object.prototypeइस तरह से "जोड़ा गया एक तरीका" को कॉल नहीं किया जा सकता है Array), और अगर आपने वास्तव में एक प्रोटोटाइप को बढ़ाया है तो सिंटैक्स काफी लंबा / बदसूरत है। स्थैतिक तरीकों के साथ सिर्फ उपयोगिता वर्ग बनाने के लिए यह लगभग हमेशा सरल होगा; इस दृष्टिकोण का एकमात्र लाभ बहुरूपता के लिए कुछ सीमित समर्थन है।
मार्क अमेरी

4
@MarkAmery हे पाल, आप इसे प्राप्त नहीं करते हैं। मैं इनहेरिटेंस नहीं खोता लेकिन इससे छुटकारा पा लेता हूं। वंशानुक्रम इतना 80 है, आपको इसके बारे में भूलना चाहिए। इस हैक का पूरा बिंदु प्रकार की कक्षाओं की नकल करना है, जो सीधे शब्दों में कहें, अतिभारित कार्य हैं। हालांकि एक वैध आलोचना है: क्या जावास्क्रिप्ट में टाइप कक्षाओं की नकल करना उपयोगी है? नहीं, यह नहीं है। बल्कि एक टाइप की गई भाषा का उपयोग करें जो उन्हें मूल रूप से समर्थन करती है। मुझे पूरा यकीन है कि आपका यही मतलब है।

7

एक और कारण कि आपको देशी वस्तुओं का विस्तार क्यों नहीं करना चाहिए :

हम Magento का उपयोग करते हैं जो प्रोटोटाइप का उपयोग करता है। जेएस और देशी वस्तुओं पर बहुत सारे सामान का विस्तार करता है। यह तब तक ठीक काम करता है जब तक आप नई सुविधाओं को प्राप्त करने का निर्णय नहीं लेते हैं और यहीं से बड़ी मुसीबतें शुरू होती हैं।

हमने अपने एक पेज पर वेबकंप्यूटर की शुरुआत की है, इसलिए आईई (क्यों?) में पूरे (देशी) इवेंट ऑब्जेक्ट को बदलने के लिए वेबकंप्यूटर-लाइट.जेएस निर्णय लेते हैं। यह निश्चित रूप से प्रोटोटाइप.जेएस को तोड़ता है जो बदले में मैगेंटो को तोड़ता है। (जब तक आप समस्या का पता नहीं लगाते, तब तक आप इसे वापस ट्रेस करने में कई घंटे लगा सकते हैं)

अगर आपको परेशानी पसंद है, तो इसे करते रहें!


4

मैं ऐसा न करने के तीन कारण देख सकता हूं (किसी एप्लिकेशन के भीतर , कम से कम), जिनमें से केवल दो को यहां मौजूद उत्तरों में संबोधित किया गया है:

  1. यदि आप इसे गलत करते हैं, तो आप गलती से विस्तारित प्रकार की सभी वस्तुओं में एक संपत्ति जोड़ सकते हैं। आसानी से उपयोग करने के चारों ओर काम किया Object.defineProperty, जो डिफ़ॉल्ट रूप से गैर-एन्यूमरेबल गुण बनाता है।
  2. आपके द्वारा उपयोग किए जा रहे लायब्रेरी के साथ कोई विरोध हो सकता है। परिश्रम से बचा जा सकता है; किसी प्रोटोटाइप में कुछ जोड़ने से पहले परिभाषित पुस्तकालयों का उपयोग करने के तरीकों को जाँचें, अपग्रेड करते समय रिलीज़ नोट्स की जाँच करें और अपने आवेदन का परीक्षण करें।
  3. आप मूल जावास्क्रिप्ट वातावरण के भविष्य के संस्करण के साथ संघर्ष का कारण हो सकते हैं।

प्वाइंट 3 यकीनन सबसे महत्वपूर्ण है। आप परीक्षण के माध्यम से यह सुनिश्चित कर सकते हैं कि आपके प्रोटोटाइप एक्सटेंशन आपके द्वारा उपयोग किए जाने वाले पुस्तकालयों के साथ कोई टकराव का कारण न बनें, क्योंकि आप तय करते हैं कि आप किन पुस्तकालयों का उपयोग करते हैं। यही नहीं मूल वस्तुओं का सच है, यह मानते हुए कि आपका कोड एक ब्राउज़र में चलता है। यदि आप Array.prototype.swizzle(foo, bar)आज को परिभाषित करते हैं, और कल Google Array.prototype.swizzle(bar, foo)क्रोम में जोड़ता है, तो आप कुछ भ्रमित सहकर्मियों के साथ समाप्त होने के लिए उत्तरदायी हैं, जो आश्चर्यचकित करते हैं कि .swizzleएमडीएन पर दस्तावेज क्या है क्यों मेल नहीं खाते।

(यह भी देखें कि प्रोटोटाइप के साथ मूटूलों की फिडिंग की कहानी को उन्होंने वेब तोड़ने से बचने के लिए ईएस 6 विधि का नाम बदलने के लिए मजबूर नहीं किया ।)

यह देशी वस्तुओं (जैसे Array.prototype.myappSwizzleबजाय परिभाषित Array.prototype.swizzle) के लिए जोड़े गए तरीकों के लिए एक एप्लिकेशन-विशिष्ट उपसर्ग का उपयोग करके परिहार्य है , लेकिन यह बदसूरत की तरह है; यह प्रोटोटाइप को बढ़ाने के बजाय स्टैंडअलोन उपयोगिता कार्यों का उपयोग करके बस के रूप में अच्छी तरह से हल करने योग्य है।


2

परफैक्ट भी एक कारण है। कभी-कभी आपको चाबियों पर लूप करने की आवश्यकता हो सकती है। इसे करने बहुत सारे तरीके हैं

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

मैं आमतौर पर इसका उपयोग for of Object.keys()करता हूं क्योंकि यह सही काम करता है और यह अपेक्षाकृत अच्छा है, चेक को जोड़ने की कोई आवश्यकता नहीं है।

लेकिन, यह बहुत धीमा है

पूर्ण परिणामों के लिए बनाम के लिए

बस अनुमान लगाना Object.keysधीमा है कि यह स्पष्ट है, Object.keys()आवंटन करना है। वास्तव में AFAIK के बाद से सभी चाबियों की एक प्रति आवंटित करना है।

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

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

यह संभव है कि जेएस इंजन किसी प्रकार की अपरिवर्तनीय कुंजी संरचना का उपयोग कर सकता है ताकि Object.keys(object)एक संदर्भ कुछ लौटाए जो अपरिवर्तनीय कुंजियों पर निर्भर object.newPropकरता है और जो पूरी तरह से नई अपरिवर्तनीय कुंजी ऑब्जेक्ट बनाता है लेकिन जो भी हो, यह स्पष्ट रूप से 15x तक धीमा है

यहां तक ​​कि जांच hasOwnProperty2x धीमी तक है।

उस सभी का मुद्दा यह है कि यदि आपके पास पूर्ण संवेदनशील कोड है और कुंजी पर लूप करने की आवश्यकता है, तो आप for inकॉल किए बिना उपयोग करने में सक्षम होना चाहते हैं hasOwnProperty। यदि आप संशोधित नहीं हुए हैं तो आप केवल यही कर सकते हैंObject.prototype

ध्यान दें कि यदि आप Object.definePropertyप्रोटोटाइप को संशोधित करने के लिए उपयोग करते हैं यदि आप जो चीजें जोड़ते हैं, वे उल्लेखनीय नहीं हैं, तो वे उपरोक्त मामलों में जावास्क्रिप्ट के व्यवहार को प्रभावित नहीं करेंगे। दुर्भाग्य से, कम से कम क्रोम 83 में, वे प्रदर्शन को प्रभावित करते हैं।

यहाँ छवि विवरण दर्ज करें

मैंने 3000 गैर-विलुप्त होने वाले गुणों को जोड़ा, ताकि किसी भी पूर्ण मुद्दों को प्रकट करने के लिए मजबूर किया जा सके। केवल 30 गुणों के साथ परीक्षण यह बताने के लिए बहुत करीब थे कि क्या कोई पूर्ण प्रभाव था।

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

फ़ायरफ़ॉक्स 77 और सफारी 13.1 में संवर्धित और अनारक्षित वर्ग के बीच पूर्ण रूप से कोई अंतर नहीं दिखाया गया है, शायद v8 इस क्षेत्र में तय हो जाएगा और आप पूर्ण मुद्दों की अनदेखी कर सकते हैं।

लेकिन, मुझे यह भी जोड़ने की कहानी हैArray.prototype.smoosh । लघु संस्करण मूटोल्स, एक लोकप्रिय पुस्तकालय है, जिसने अपना स्वयं का बनाया है Array.prototype.flatten। जब मानकों की समिति ने एक देशी को जोड़ने की कोशिश की तो Array.prototype.flattenउन्होंने पाया कि बहुत सारी साइटें तोड़े बिना नहीं रह सकतीं। ब्रेक के बारे में पता लगाने वाले देवों ने es5 पद्धति smooshको एक मजाक के रूप में नामित करने का सुझाव दिया लेकिन लोगों ने इसे मजाक नहीं समझते हुए इसे गलत बताया। वे के flatबजाय पर बसेflatten

कहानी का नैतिक यह है कि आपको देशी वस्तुओं का विस्तार नहीं करना चाहिए। यदि आप करते हैं तो आप अपने सामान को तोड़ने के एक ही मुद्दे में चला सकते हैं और जब तक कि आपका विशेष पुस्तकालय MooTools के रूप में लोकप्रिय नहीं होता है, ब्राउज़र विक्रेताओं को आपके द्वारा उत्पन्न समस्या के आसपास काम करने की संभावना नहीं है। यदि आपकी लाइब्रेरी उस लोकप्रिय को प्राप्त करती है, तो आपके द्वारा जारी किए गए मुद्दे के आसपास हर किसी को काम करने के लिए मजबूर करने का यह मतलब होगा। तो, कृपया देशी वस्तुओं का विस्तार न करें


रुको, hasOwnPropertyआपको बताता है कि संपत्ति वस्तु या प्रोटोटाइप में है या नहीं। लेकिन for inलूप आपको केवल मिलनसार गुण देता है। मैंने अभी-अभी यह कोशिश की है: गैर-विलुप्त होने वाली संपत्ति को ऐरे प्रोटोटाइप में जोड़ें और यह लूप में दिखाई नहीं देगा। काम करने के लिए सबसे सरल लूप के लिए प्रोटोटाइप को संशोधित करने की आवश्यकता नहीं है।
ygoe

); लेकिन यह अन्य कारणों के लिए एक बुरी प्रथा अभी भी
GMAN
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.