เนมสเปซทั่วโลกจะมีมลพิษหมายความว่าอย่างไร


92

เนมสเปซทั่วโลกจะมีมลพิษหมายความว่าอย่างไร

ฉันไม่เข้าใจจริงๆว่าเนมสเปซทั่วโลกมีมลพิษหมายความว่าอย่างไร


1
การเชื่อมโยงสำหรับการอ้างอิงในอนาคต: JavaScript Namespace Declaration
blong

คำตอบ:


124

หมายเหตุด่วนเกี่ยวกับการรวบรวมขยะ

เนื่องจากตัวแปรสูญเสียขอบเขตจึงมีสิทธิ์ได้รับการรวบรวมขยะ หากมีการกำหนดขอบเขตทั่วโลกก็จะไม่มีสิทธิ์ได้รับการรวบรวมจนกว่าเนมสเปซส่วนกลางจะสูญเสียขอบเขต

นี่คือตัวอย่าง:

var arra = [];
for (var i = 0; i < 2003000; i++) {
 arra.push(i * i + i);
}

การเพิ่มสิ่งนี้ในเนมสเปซส่วนกลางของคุณ (อย่างน้อยสำหรับฉัน) ควรโฆษณาการใช้หน่วยความจำ 10,000 กิโลไบต์ (win7 firefox) ซึ่งจะไม่ถูกรวบรวม เบราว์เซอร์อื่นอาจจัดการสิ่งนี้แตกต่างกัน

ในขณะที่มีรหัสเดียวกันนั้นในขอบเขตที่อยู่นอกขอบเขตเช่นนี้:

(function(){
 var arra = [];
 for (var i = 0; i < 2003000; i++) {
  arra.push(i * i + i);
 }
})();

จะอนุญาตให้arraสูญเสียขอบเขตหลังจากการปิดดำเนินการและมีสิทธิ์ได้รับการเก็บขยะ

เนมสเปซทั่วโลกคือเพื่อนของคุณ

แม้จะมีการเรียกร้องมากมายเกี่ยวกับการใช้เนมสเปซทั่วโลก แต่ก็เป็นเพื่อนของคุณ และเช่นเดียวกับเพื่อนที่ดีคุณไม่ควรละเมิดความสัมพันธ์ของคุณ

อ่อนโยน

อย่าละเมิด (โดยปกติเรียกว่า "สร้างมลพิษ") เนมสเปซทั่วโลก และสิ่งที่ฉันหมายถึงอย่าใช้เนมสเปซส่วนกลางคือ - อย่าสร้างตัวแปรส่วนกลางหลายตัว นี่คือตัวอย่างที่ไม่ดีของการใช้เนมสเปซส่วนกลาง

var x1 = 5;
var x2 = 20;
var y1 = 3
var y2 = 16;

var rise = y2 - y1;
var run = x2 - x1;

var slope = rise / run;

var risesquared = rise * rise;
var runsquared = run * run;

var distancesquared = risesquared + runsquared;

var distance = Math.sqrt(dinstancesquared);

สิ่งนี้จะสร้างตัวแปรส่วนกลาง 11 ตัวซึ่งอาจถูกเขียนทับหรือตีความผิดที่ใดที่หนึ่ง

เป็นคนเก่ง

แนวทางที่เป็นประโยชน์มากขึ้นซึ่งไม่ก่อให้เกิดมลพิษต่อเนมสเปซส่วนกลางคือการรวมสิ่งนี้ทั้งหมดไว้ในรูปแบบโมดูลและใช้ตัวแปรส่วนกลางเพียงตัวเดียวในขณะที่เปิดเผยหลายตัวแปร

นี่คือตัวอย่าง: (โปรดทราบว่านี่เป็นเรื่องง่ายและไม่มีการจัดการข้อผิดพลาด)

//Calculate is the only exposed global variable
var Calculate = function () {
 //all defintions in this closure are local, and will not be exposed to the global namespace
 var Coordinates = [];//array for coordinates
 var Coordinate = function (xcoord, ycoord) {//definition for type Coordinate
   this.x = xcoord;//assign values similar to a constructor
   this.y = ycoord;
  };

  return {//these methods will be exposed through the Calculate object
   AddCoordinate: function (x, y) {
   Coordinates.push(new Coordinate(x, y));//Add a new coordinate
  },

  Slope: function () {//Calculates slope and returns the value
   var c1 = Coordinates[0];
   var c2 = Coordinates[1];
   return c2.y - c1.y / c2.x - c1.x;//calculates rise over run and returns result
  },

  Distance: function () {
   //even with an excessive amount of variables declared, these are all still local
   var c1 = Coordinates[0];
   var c2 = Coordinates[1];

   var rise = c2.y - c1.y;
   var run = c2.x - c1.x;

   var risesquared = rise * rise;
   var runsquared = run * run;

   var distancesquared = risesquared + runsquared;

   var distance = Math.sqrt(distancesquared);

   return distance;
  }
 };
};

//this is a "self executing closure" and is used because these variables will be
//scoped to the function, and will not be available globally nor will they collide
//with any variable names in the global namespace
(function () {
 var calc = Calculate();
 calc.AddCoordinate(5, 20);
 calc.AddCoordinate(3, 16);
 console.log(calc.Slope());
 console.log(calc.Distance());
})();

10
การเก็บตัวแปรไว้ในการปิดเพื่อให้แน่ใจว่ามีการรวบรวมขยะ
theJava

2
คำตอบที่น่าสนใจมากคุณสามารถอธิบายเราได้ไหมว่าอะไรคือความแตกต่างระหว่างการใช้ผลตอบแทนเหมือนกับที่คุณทำในขอบเขตของคุณและใช้ตัวอย่าง Calculate.prototype.Slope()นอกขอบเขต มันจะสมบูรณ์แบบมากที่จะอธิบายแนวคิดอื่นที่ใกล้เคียงกับปัญหานี้!
Ludo

ขอบคุณสำหรับคำอธิบายที่ดี คำถามด่วน: คุณต้องการเห็นอะไรเกี่ยวกับการจัดการข้อผิดพลาดในข้อมูลโค้ดนั้น
Sentenza

@ เซนเทนซ่า - ขึ้นอยู่กับว่าจะเกิดอะไรขึ้นหากมีข้อผิดพลาดในบรรทัด หากไม่มีอะไรก็ไม่จำเป็นต้องมีการจัดการข้อผิดพลาด หากเป็นเรื่องสำคัญอาจเป็นการทดสอบบางอย่างเพื่อให้แน่ใจว่าการหารด้วย 0 จะไม่เกิดขึ้นและข้อความหรือการตอบสนองเพื่อบ่งชี้ความพยายามที่ล้มเหลว (บางครั้งก็หมายถึงการล้มเหลวโดยไม่โต้ตอบ บางทีการทดสอบบางอย่างเพื่อให้แน่ใจว่าตัวเลขเป็นตัวเลขไม่ใช่ข้อความ โดยรวมแล้วการจัดการข้อผิดพลาดขึ้นอยู่กับผู้ที่ใช้รหัส หากเป็นเพียงคุณคุณอาจจะไม่รู้ว่าจะไม่ผ่านการโต้แย้งที่รุนแรง นี่เป็นตัวอย่างที่ค่อนข้างง่าย :)
Travis J

20

ใน JavaScript การประกาศภายนอกฟังก์ชันอยู่ในขอบเขตส่วนกลาง ลองพิจารณาตัวอย่างเล็ก ๆ นี้:

var x = 10;
function example() {
    console.log(x);
}
example(); //Will print 10

ในตัวอย่างข้างต้นxมีการประกาศในขอบเขตทั่วโลก ขอบเขตลูกใด ๆ เช่นที่สร้างขึ้นโดยexampleฟังก์ชันจะสืบทอดสิ่งที่ประกาศในขอบเขตหลักได้อย่างมีประสิทธิภาพ (ในกรณีนี้นั่นเป็นเพียงขอบเขตส่วนกลาง)

ขอบเขตลูกใด ๆ ที่ประกาศตัวแปรที่ประกาศในขอบเขตส่วนกลางอีกครั้งจะทำให้ตัวแปรโกลบอลเป็นเงาซึ่งอาจก่อให้เกิดข้อบกพร่องที่ไม่ต้องการและยากที่จะติดตาม:

var x = 10;
function example() {
    var x = 20;
    console.log(x); //Prints 20
}
example();
console.log(x); //Prints 10

มักไม่แนะนำให้ใช้ตัวแปรส่วนกลางเนื่องจากอาจทำให้เกิดปัญหาเช่นนี้ หากเราไม่ได้ใช้varคำสั่งภายในexampleฟังก์ชันเราจะเขียนทับค่าxในขอบเขตส่วนกลางโดยไม่ได้ตั้งใจ:

var x = 10;
function example() {
    x = 20; //Oops, no var statement
    console.log(x); //Prints 20
}
example();
console.log(x); //Prints 20... oh dear

หากคุณต้องการอ่านรายละเอียดเพิ่มเติมและเข้าใจมันอย่างถูกต้องผมขอแนะนำให้ไปผ่านข้อกำหนด ECMAScript อาจไม่ใช่เรื่องที่น่าตื่นเต้นที่สุดสำหรับการอ่าน แต่จะช่วยได้ไม่สิ้นสุด


8

เมื่อคุณประกาศตัวแปรส่วนกลางฟังก์ชัน ฯลฯ พวกเขาไปที่เนมสเปซส่วนกลาง นอกเหนือจากปัญหาด้านประสิทธิภาพ / หน่วยความจำ (ซึ่งอาจเกิดขึ้น) คุณมีแนวโน้มที่จะพบกับการปะทะกันของชื่อที่ไม่ดีเมื่อคุณจะกำหนดตัวแปรที่สำคัญใหม่หรือไม่ใช้ค่าที่คุณคิดว่าคุณใช้

ควรหลีกเลี่ยงการกำหนดสิ่งต่างๆในเนมสเปซส่วนกลาง


1
วิธีหลีกเลี่ยงการกำหนดสิ่งต่างๆในเนมสเปซส่วนกลางคือการใช้ตัวแปรโลคัล (ประกาศด้วย "var" ภายในฟังก์ชัน) แต่ตัวแปรนั้นก็คือ ... local สำหรับฟังก์ชัน สิ่งนี้ควรทำให้มากที่สุด
Stéphane Glondu
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.