SoFunction
Updated on 2025-04-14

prototype Element study notes (Part 1)

Let me first talk about Element's technical ideas for DOM expansion. I also read the code for a day, so I have some experience.
Using prototype, the most common code we use is $('div1'). This will obtain the extended element object, and then we can use its various extended methods, such as:
$('div1').addClassName('loading').show();
Therefore, the expansion of our research on Element should be used as the entry point.
function $(element) {
if ( > 1) {
for (var i = 0, elements = [], length = ; i < length; i++)
($(arguments[i]));
return elements;
}
if ((element))
element = (element);
return (element);
}
This function can handle multiple parameters with a clever recursion, which really makes me amazed. The key in the code is: (element). Before extend, element was just an ordinary DOM object, and it was extended after extend. It can be seen that the secret is in extend.
Since it is (element), of course we cannot study extend alone, but we must first understand what Element is.
(function() {
var element = ;
= function(tagName, attributes) {
attributes = attributes || { };
tagName = ();
var cache = ;
if ( && ) {
tagName = ' <' + tagName + ' name="' + + '">';
delete ;
return ((tagName), attributes);
}
if (!cache[tagName]) cache[tagName] = ((tagName));
return (cache[tagName].cloneNode(false), attributes);
};
(, element || { });
}).call(window);
This kind of code has a more personalized personality, and the basic structure is: (function(){...}).call(window); Therefore, when you see this structure, you must know that this appears in the ellipsis part points to window.
var element=; This line is not difficult to understand, but the key is that it has not been defined at this time. The following is to define a class: class, which has two parameters: tagName and attributes. Its function is to create an element and put the DOM object corresponding to a pure specified tag into the cache. After the element is created, the specified attribute value is written. Here is a reminder:
The functions of the two functions of writeAttribute and readAttribute are obviously read and write attributes, but its code is not simple. Its complexity mainly comes from the different methods of reading and writing attributes in different browsers.
This is the definition of the constructor of the Element class. After it, = { }; cache, what is the cache, which is not easy to describe, and the cache of the pure version of DOM element objects of various labels? This is so disgusting. Immediately followed by a: ={...}, here, almost all extension methods are defined. The extension methods here all have a feature. None of the code uses this, they are honestly passed in an element reference. This is a foreshadowing, and there is a reason why it is defined like this. Let me explain it later.
Now that Element has roughly said it, I have to talk about it.
= (function() {
if ()
return ;
var Methods = { }, ByTag = ;
var extend = (function(element) {
if (!element || element._extendedByPrototype ||
!= 1 || element == window) return element;
var methods = (Methods),
tagName = , property, value;
// extend methods for specific tags
if (ByTag[tagName]) (methods, ByTag[tagName]);
for (property in methods) {
value = methods[property];
if ((value) && !(property in element))
element[property] = ();
}
element._extendedByPrototype = ;
return element;
}, {
  refresh: function() {
// extend methods for all tags (Safari doesn't need this)
if (!) {
(Methods, );
(Methods, );
}
}
});
();
return extend;
})();
I'm not sure about the principle of the first line. Not to mention it, the following code seems complicated, so I'll extract its general structure:
var extend=(function(element){……},{refresh:function(){……}});
In extend, the first function is to obtain the method from it and copy it into this element. Here is mainly based on the following considerations:
1. If the element is a Form, you have to use the method
2. If the element is an input element in the form, you must take the method from it.
3. All elements should obtain a general method from it (considered by refresh).
In other words, there are many situations to consider here. It should have been an if statement, but one is cleverly designed here. This solves this problem.
if ((value) && !(property in element))
element[property] = ();
If a member in Methods is not a function or the function already exists in an element, it will not be overwritten. Here comes the key point, that (), at this time, the previous foreshadowing takes effect, and the function of methodize is to pass the current caller into the method. And passed in as the first parameter. It is generally used:
=();
In this way, when called, the obj object will be passed into the function name function as the first parameter.
So far, the general idea in this extend function should be clear. There is still a question that is not clear: according to the element's tagName, which Methods should be obtained from, so we need to understand the details of ByTag, search and find:
(, {
"FORM": (),
"INPUT": (),
"SELECT": (),
"TEXTAREA": ()
});
OK, that's about it.