This time I will bring you three methods of maintaining JS code. What are theprecautionsfor maintaining JS code? The following is a practical case, let’s take a look.
maintain. In other languages, consider using existing objects as libraries to accomplish development tasks. In JS, we can treat existing objects as a background on which anything can be done. You should treat existing JS objects like a utility library.
Do not overwrite methods
Do not add new methods
Do not delete methods
When you are the only developer in the project, because you understand them, you are right They have expectations and these kinds of modifications are easy to handle. When working on a large project with a team, changes like these can cause a lot of confusion and waste a lot of time.
Not overriding methods
In JS, the worst practice ever is to override a method on an object you do not own. It is incredibly easy to overwrite an existing method in JS. Even the sacred document.getElementById() method is no exception and can be easily overridden. Maybe you have seen a pattern similar to the following (this approach is also called "function hijacking"):
// 不好的写法document._originalGetElementById = document.getElementById;document.getElementById = function (id) { if (id === 'window') { return window; } else { return document._originalGetElementById(id); } }
In the above example, the "pointer" of a native method document.getElementById() is saved in document._originalGetElementById , for subsequent use. Then, document.getElementById() is overridden by a new method. The new method sometimes calls the original method, but in one case it doesn't. This "overriding and reliable degradation" pattern is at least as bad as overriding a native method, maybe worse, because document.getElementById() sometimes works as expected and sometimes doesn't. On a large project, one such problem can result in a lot of wasted time and money.
No new methods
It is very simple to add methods to existing objects in JS. Just create a function and assign it to a property of an existing object, making it a method. This approach can modify all types of objects.
// 不好的写法 - 在 DOM对象 上增加了方法document.sayImAwesome = function () { alert("You're awesome."); }// 不好的写法 - 在原生对象上增加了方法Array.prototype.reverseSort = function () { return this.sort().reverse(); }// 不好的写法 - 在库对象上增加了方法YUI.doSomething = function () { // 代码}
It is almost impossible to prevent you from adding methods to any object (ES5 adds three new methods to do this, which will be introduced later). Adding methods to objects you don't own is a big problem and can lead to naming conflicts. Just because an object doesn't have a method at the moment doesn't mean it won't have one in the future. What's worse is that if the native method behaves inconsistently with your method in the future, you will be trapped in a code maintenance nightmare.
We need to learn lessons from the development history of the Prototype JS class library. Prototype is very famous from the perspective of modifying various JS objects. It adds methods to the DOM and native objects very freely. In fact, most of the library's code is defined as extending existing objects rather than creating objects yourself. The developers of Prototype view the library as a complement to JS. In versions less than 1.6, Prototype implements a document.getElementsByClassName() method. Maybe you recognize this method because it is officially defined in HTML5 and it standardizes the usage of Prototype.Prototype’s document.getElementsByClassName() method returns an array containing elements with the specified CSS class name. Prototype also adds a method on the array, Array.prototype.each(), which iterates over the array and executes a function on each element. This allows developers to write code like:
document.getElementsByClassName('selected').each(doSomething);
Until HTML5 standardizes this method and browsers start implementing it natively, the code will be problem-free. When the Prototype team knew that native document.getElementsByClassName() was coming, they added some defensive code, as follows:
if (!document.getElementsByClassName) { document.getElementsByClassName = function (classes) { // 非原生实现 }; }
So Prototype just defines document.getElementsByClassName() when it doesn't exist. This seems like the problem is solved, but there is another important fact: HTML5 document.getElementsByClassName() does not return an array, so the each() method does not exist at all. The native DOM methods use a specialized collection type called NodeList. document.getElementsByClassName() returns a NodeList to match other DOM method calls.
If the document.getElementsByClassName() method is implemented natively in the browser, then since NodeList does not have an each() method, whether it is the native or the each() method added by Prototype, it will trigger a JS error. The end result is that Prototype users have to not only upgrade the class library code but also modify their own code, which is really a maintenance nightmare.
从Prototype的错误中可以学到,你不可能精确预测JS将来会如何变化。标准已经进化了,它们经常会从诸如Prototype这样的库代码中获得一些线索来决定下一代标准的新功能。事实上,原生的Array.prototype.forEach()方法在ECMAScript5有定义,它与Prototype的each()方法行为非常类似。问题是你不知道官方的功能与原生会有什么样的不同,甚至是微小的区别也将导致很大的问题。
大多数JS库代码有一个插件机制,允许为代码库安全地新增一些功能。如果想修改,最佳最可维护的方式是创建一个插件。
不删除方法
删除JS方法和新增方法一样简单。当然,覆盖一个方法也是删除已存在的方法的一种方式。最简单的删除一个方法的方式就是给对应的名字赋值为null。
// 不好的写法 - 删除了DOM方法document.getElementById = null;
将一个方法设置为null,不管它以前是怎么定义的,现在它已经不能被调用到了。如果方法是在对象的实例上定义的(相对于对象的原型而言),也可以使用delete操作符来删除。
var person = { name: 'Nicholas'};delete person.name;console.log(person.name); // undefined
上例中,从person对象中删除了name属性。delete操作符只能对实例的属性和方法起作用。如果在prototype的属性或方法上使用delete是不起作用的。例如:
// 不影响delete document.getElementById;console.log(document.getElementById('myelement')); // 仍然能工作
因为document.getElementById()是原型上的一个方法,使用delete是无法删除的。但是,仍然可以用对其赋值为null的方式来阻止被调用。
无需赘述,删除一个已存在对象的方法是糟糕的实践。不仅有依赖那个方法的开发者存在,而且使用该方法的代码有可能已经存在了。删除一个在用的方法会导致运行时错误。如果你的团队不应该使用某个方法,将其标识为“废弃”,可以用文档或者用静态代码分析器。删除一个方法绝对应该是最后的选择。
反之,不删除你拥有对象的方法实际上是比较好的实践。从库代码或原生对象上删除方法是非常难的事情,因为第三方代码正依赖于这些功能。在很多案例中,库代码和浏览器都会将有bug或不完整的方法保留很长一段时间,因为删除它们以后会在数不胜数的网站上导致错误。
相信看了本文案例你已经掌握了方法,更多精彩请关注php中文网其它相关文章!
推荐阅读:
The above is the detailed content of Three ways to maintain JS code. For more information, please follow other related articles on the PHP Chinese website!