Detailed JavaScript comparison of property and attribute similarities and differences

Source: Internet
Author: User
Tags comparison extend

The property is an attribute in the DOM, an object in JavaScript, an attribute on an HTML tag, and its value can only be a string; many friends are easily confused.





analyzing property and attribute based on JavaScript





There is such a piece of code in HTML:





<input id= "in_1" value= "1" sth= "whatever" >





Simply create an input field on an HTML page (note that a property "sth" that does not exist in the DOM is added to this tab), and then execute the following statement in JS





var in1 = document.getElementById (' in_1 ');





EXECUTE statement





Console.log (in1);





From the print result of the console, you can see that in1 contains a property named "Attributes", which is of type NamedNodeMap, with "id" and "value" two basic properties, but no "sth" this custom property.





Attributes:namednodemap


Value: "1"


ID: "In_1"





Some console may not print properties on in1, then you can print the properties you want to observe by executing the following command:





Console.log (in1.id); ' In_1 '


Console.log (In1.value); 1


Console.log (IN1.STH); Undefined





As you can see, the three properties in the label, only "id" and "value" are created on the in1, and "Sth" is not created. This is because every DOM object has its default basic properties, and when created, it creates only these basic properties, and the attributes we customize in the tag tag are not placed directly into the DOM.





Let's do an extra test, create another input tag, and do something similar:





Html:





<input id= "In_2" >





Js:





var in2 = document.getElementById (' in_2 ');


Console.log (in2);





You can see from the print information:





ID: "In_2"


Value:null





Although we do not define "value" in tag, it is created as Dom initializes, because it is the default basic property of the DOM. From this we can draw the conclusion that:





The DOM has its default basic properties, which are called "property", which, in any case, are created on the DOM object at the time of initialization.


If these properties are assigned in tag, the values are assigned to the DOM's same name as the initial value.





Now go back to the first input ("#in_1") and we'll ask, "Where's sth?" Don't worry, we'll print out the attributes this property to see





Console.log (in2);





There are several properties:





0:id


1:value


2:sth


Length:3


__PROTO__: NamedNodeMap





The original "Sth" was put into the attributes object, which sequentially recorded the number of attributes and attributes we defined in tag. At this point, if you print the second input label attributes, you will find that there is only one "id" attribute, "Length" is 1.





As you can see from here, attributes is a subset of the property that holds the attributes defined on the HTML tag. If you further explore each of the attributes in attitudes, you will find that they are not simple objects, it is a attr type of object, with NodeType, nodename and other attributes. On this point, we will study it later. Note that the Print attribute property does not directly get the object's value, but instead gets a string containing the property name and value, such as:





Console.log (IN1.ATTIBUTES.STH); ' Sth= ' whatever '





From this we can conclude that:





The attributes and values defined in the HTML tag will hold the Attributes property of the DOM object;


The types in JavaScript of these attribute attributes are attr, not just the property names and values;





So what happens if we change the value of the property and attribute? Execute the following statement:





In1.value = ' new value of Prop ';


Console.log (In1.value); ' New value of Prop '


Console.log (In1.attributes.value); ' value= ' 1 '





At this point, the value of the input column in the page becomes "new value of Prop", and value in Propety becomes a new value, but attributes is still "1". It can be inferred from this that the values of property and attribute with the same name are not two-way bound.





If, in turn, you set the value in attitudes, what would be the effect?





In1.attributes.value.value = ' new value of attr ';


Console.log (In1.value); ' New value of attr '


Console.log (In1.attributes.value); ' New value of attr '





At this point, the input column in the page is updated and the value in the property has changed. In addition, executing the following statement will get the same result





In1.attributes.value.nodeValue = ' new value of attr ';





From this, we can draw a conclusion:





Property can be synchronized from the attribute;


attribute does not synchronize the value on the property;


The data binding between attribute and property is one-way,attribute->property;


Changing any value on the property and attribute will reflect the update to the HTML page;





Analyzing attribute and property based on jquery





So what about the attr and prop methods in jquery?





First, use Jquery.prop to test





$ (in1). Prop (' Value ', ' New prop Form $ ');





Console.log (In1.value); ' New prop form $ '


Console.log (In1.attributes.value); ' 1 '





The value of the input column is updated, but the attribute is not updated.





And then test it with jquery.attr.





$ (in1). attr (' value ', ' New attr form $ ');





Console.log (In1.value); ' New attr form $ '


Console.log (In1.attributes.value); ' New attr form $ '





The value of the input column is updated, and both the property and attribute are updated.





From the above test phenomenon can be inferred, jquery.attr and Jquery.prop basic and native operation method effect is consistent, property will get synchronization from attribute, but attribute does not get synchronization from property. So how exactly is jquery implemented?





Below, we look at the source code of JQUERY.ATTR and Jquery.prop.


jquery source


$ (). Prop Source Code

JQuery.fn.extend ({
Prop:function (name, value) {
Return access (this, jquery.prop, name, value, Arguments.length > 1);
},
..///Removeprop method
});

$ (). attr Source Code

JQuery.fn.extend ({
Attr:function (name, value) {
Return access (this, jquery.attr, name, value, Arguments.length > 1);
},
..///Removeattr method
});

Both attr and prop call access methods to access the elements of the DOM object, so to learn more, you must read access's implementation source code.


Jquery.access

  This is a versatile function that can be used to get or set the value of a set//  if this "value" is a function, then the function is executed//  @param  elems,  element Set// @ param fn,  methods for processing elements//  @param  key,  element name//  @param  value,  new Values// @ param chainable,  whether a chained call//  @param  emptyget,//  @param  raw,  Element is a non-function object Var access = jquery.access = function ( elems, fn, key , value, chainable, emptyget, raw )  {    var i =  0,                         //  Iteration Count         length  = elems.length,        //  element Length          bulk = key == null;             //  determines whether there is a specific key (property name)     //  If multiple properties exist, recursion is used to access these values individually     if   ( jquery.type ( key )  ===  "Object"  )  {     
   chainable = true;         for  ( i in key )  {             jquery.access ( elems, fn, i, 
key[i], true, emptyget, raw );        &NBSP}     //  set a value      } else if  ( value !== undefined )  {     
   chainable = true;         if  ( !jquery.isfunction ( value )  )  {    //  If the value is not a function             raw = true;        &NBSP}         if  (  bulk )  {            // bulk  operations run against the entire set              //  If the property name is empty and the property name is not a function, the external processing method fn and value is used to perform the Operation              if  ( raw )  {     
           fn.call ( elems, value );                 fn =
 null;             // ...except when  Executing function values       &Nbsp;     //  if value is a function, then reconstruct the processing method fn              //  This new FN will pass value function as a callback function to the old processing method              } else {      
          bulk = fn;                 fn =  function ( elem, key, value )  {                     return bulk.call ( jQuery (
 elem ), value );
                };             }          }         if  ( fn )  {    //  Use the processing method fn to process each element in the collection of elements             for  (  ; i < length; i++ )  {                 FN ( elems[i], key, raw ? value : 
Value.call ( ELEMS[I], I, FN ( elems[i], key )  )  );                 //  If value is a Funciton, then first use this function to return a value and pass in FN                       }     }     
return chainable ?         elems :               If it is a chained call, return the element collection         // gets     
    bulk ?
            fn.call ( elems )  :             LENGTH ? FN ( elems[0],
 key )  : emptyGet; };



Although the access method is not long, but very winding, it is not easy to read fully, so you can simplify access for jQuery.fn.attr calls.


Access calls in Jquery.fn.attr/jquery.fn.prop

$ (). attr Invocation Mode:

$ (). attr (PropertyName)//Get a single property
$ (). attr (propertyname, value)//Set individual properties
$ (). attr (properties)//Set multiple attributes
$ (). attr (propertyname, function)//callback function on property call

The prop invocation is the same as the attr, which is not repeated here. For the sake of simplicity, only the first and second invocation methods are studied here.

Call statement:

Access (this, jquery.attr, name, value, Arguments.length > 1);

Simplified access:

 elems  current JQuery object, possibly containing multiple DOM objects// fn jquery.attr method// name  property name// value Value of   Property// chainable  if value is null, chainable is false, otherwise chainable is true var access =  Jquery.access = function ( elems, fn, key, value, chainable, emptyget,  raw )  {    var i = 0,                         //   Iteration Count         length = elems.length,         //  Number of attributes         bulk =  false;                //  Key != null     if  ( value !== undefined )  {     //  if value is not empty, set the new value or return the value of the property         chainable = true;         raw = true;                 // value is not a function          if  ( fn )  {    // fn to jquery.attr              for  ( ; i <  length; i++ )  {                 FN ( elems[i], key, value);         //
 jquery.attr (Elems, key, value);             }         &NBSP}     }           if (chainable)  {            // value is not empty, Represents a Get         return elems;         //  return element Implementation chained call     } else {      
  if (length)  {        //  returns the property value of the first element if the element collection length is not zero             RETURN FN (Elems[0], key);
     // jquery.attr (Elems[0], key);         } else {             return emptyGet;        //  Returns a default value, here is undefined         }     };



By simplifying the code, you know that access works by traversing the collection of elements that the last $ call gets, and calls the FN function on it. In Jquery.attr and Jquery.prop, access is used to traverse element set merging to control attribute and property. Access's source code has a number of conditional transfer codes, it seems dazzling, the ultimate goal is to be able to implement the elements set variables and complete different operations, complex code to make the interface of jquery more simple, can greatly improve the reusability of code, meaning that the amount of code, Increase the density of the code so that the JS file size is reduced.

These are the digression, now back to $ (). attr and $ (). Prop implementation. In general, both prototyping methods use access to make variables on the set of elements and invoke the Jquery.prop and jquery.attr methods for each element. To note that The Jquery.prop and jquery.attr here are not the methods on the prototype chain, but the method of the JQuery object itself, which is extended using the Jquery.extend method (JQuery.fn.prop and JQuery.fn.attr is the use of Jquery.fn . Extend the method is extended.

Let's look at the source code for these two methods.


Jqury.attr

Jquery.extend ({    attr: function ( elem, name, value )  {         var hooks, ret,       
      nType = elem.nodeType;    //  Get node type         //  if  elem is empty or NodeType is the following type          //         2: Attr,  Properties,  Child nodes have text, entityreference         //          3: Text,  text content in an element or attribute         //          8: Comment,  Notes          //  do not perform any action         if  ( !elem | |  ntype === 3 | |  ntype === 8 | |  nType === 2 )  {           
 return;         }         //  If you support the Attitude method,  invoke the property method         if  ( typeof  elem.getattribute === strundefined )  {        
    return jquery.prop ( elem, name, value );         }         //  If the node type of the Elem is not an element (1)         if  ( nType !== 1  ||  !jquery.isxmldoc ( elem )  )  {         
   name = name.tolowercase ();             //  for browser compatibility, get hook function, handle some special elements       
      hooks = jquery.attrhooks[ name ] | |                  ( 
JQuery.expr.match.bool.test ( name )  ? boolHook : nodeHook );        &NBSP}         if  (  value !== undefined )  {        //  If value is not undefined, execute "SET"             if  (  value === null )  {             //  if value is null, the attribute             is removed      jquery.removeattr ( elem, name );                  } else if  ( hooks &&  "Set"  in hooks &&   (Ret = hooks.set ( elem, value, name ))  !== undefined )  {                return  ret;                     //  Use hook function              } else {                         //  using Dom's SetAttribute method                  elem.setattribute ( name,  value +  ""  ); &Nbsp;       //  Note that you want to convert value to string because all attribute values are string   
              return value;             }          //  if value is undefined, execute "get"         } else  if  ( hooks &&  "Get"  in hooks &&  (ret =  hooks.get ( elem, name ))  !== null   {             return ret;             //  using hook function         } else {             ret = jquery.find.attr ( elem,  name );     //  actually called Sizzle.attr, which deals with compatibility issues to get the value of the attribute              //  returns the obtained value           
  return ret == null ?                 undefined
&NBSP:                 ret;         }     },     .});



from code can be found that Jquery.attr calls the GetAttribute and SetAttribute methods.

jqeury.prop

Jquery.extend ({    ...         prop: function (  elem, name, value )  {        var ret,  hooks, notxml,             ntype =
 elem.nodeType;         //  Filter notes, Attr, element text content          if  ( !elem | |  ntype === 3 | |  ntype === 8 | |  nType === 2 )  {           
 return;         }         notxml =  ntype !== 1 | |
 !jquery.isxmldoc ( elem );         if  ( notxml )  {         //  If not element             name =  jquery.propfix[ name ] | |  name;    //  Fix Property name              hooks = jQuery.propHooks[ name ];         //  get hook function         }          if  ( value !== undefined )  {         //  Execute "SET"             return  hooks &&  "Set"  in hooks &&  (Ret = hooks.set (
 elem, value, name ))  !== undefined ?                 ret :                          //  Call hook function                   ( elem[ name ] = value );    //  directly to elem[ Name] Assignment         } else {                              //  execute "get"              return hooks &&  "Get"  in hooks &&  (ret = 
Hooks.get ( elem, name ))  !== null ?                 ret :                 //  Call hook function                  elem[ name ];        //  return directly to Elem[name]         }           ..});



Jquery.prop is directly manipulating the property on the DOM object.

By comparing Jquery.prop and Jquery.attr, the former operates directly on the property of the DOM object, and the latter invokes the SetAttribute and GetAttribute methods. What is the method of SetAttribute and GetAttribute methods? What's the effect?


SetAttribute and GetAttribute

Based on the input box used before the test, execute the following code:

In1.setattribute (' Value ', ' New attr from setattribute ');

Console.log (In1.getattribute (' value ')); ' New attr from SetAttribute '
Console.log (In1.value); ' New attr from SetAttribute '
Console.log (In1.attributes.value); ' Value=? ' New attr from SetAttribute "', is actually a attr object

After the setattribute is executed, it is like changing the property in the attributes directly;
The result of the getattribute is exactly the same as the result of accessing the property, and does not return a attr object as if it were a direct access attritudes.


A special example


Href





However, is not all the tags, all attributes are maintained to maintain such characteristics? Now let's look at the attribute/attribute of href.





First create a label in HTML:





<a href= ' page_1.html ' id= ' a_1 ' ></a>





Execute the following code in the JS script:





Console.log (A1.HREF); ' File:///D:/GitHub/JS/html/test_01/page_1.html '


Console.log (A1.getattribute (' href ')); ' Page_1.html '





As you can see, the property is an absolute path, and the attribute has a relative path to keep. So what happens if you change these values?





Change attribute:





A1.setattribute (' href ', ' page_2.html '); Relative path


Console.log (A1.HREF); ' File:///D:/GitHub/JS/html/test_01/page_2.html '


Console.log (A1.getattribute (' href ')); ' Page_2.html '





A1.setattribute (' href ', '/page_3.html '); Root directory path


Console.log (A1.HREF); ' File:///D:/page_3.html '


Console.log (A1.getattribute (' href ')); '/page_3.html '





Change Property:





A1.href = ' home.html '; Relative path


Console.log (A1.HREF); ' File:///D:/GitHub/JS/html/test_01/home.html '


Console.log (A1.getattribute (' href ')); ' Home.html '





A1.href = '/home.html '; Root directory path


Console.log (A1.HREF); ' File:///D:/home.html '


Console.log (A1.getattribute (' href ')); '/home.html '





As you can see from here, href is a special attribute/attribute, both of which are bound in two directions, and changing either side results in a change in the value of the other party. Furthermore, this is not a simple two-way binding, and the href in the property always holds the absolute path, whereas the href in attribute preserves the relative path.





See here, the distinction between attribute and property is a little more, however, this makes people become more puzzled. Are there any other similar special examples?


Id

Try changing the ID in the property:

a1.id = ' new_id ';
Console.log (a1.id); ' new_id '
Console.log (A1.getattribute (' id ')); ' new_id '

Oh, my God, now the ID in the attribute is synchronized from the ID in the property, the data direction becomes the property <=> attribute;


Disabled

To see disabled This property, we add the "disabled" feature to the first:

<input id= "in_1" value= "1" sth= "whatever" disabled= ' disabled ' >//At this time the input has been disabled

Then execute the following code:

Console.log (in1.disabled); True
In1.setattribute (' disabled ', false); Sets the disabled in attribute, whether false or null, and does not cancel the disable
Console.log (in1); True
Console.log (In1.getattribute (' disabled ')); ' False '

Changing the disabled in attributes does not change the property, nor does it remove the disabling effect of the input bar.


If you change to the following code:

Console.log (in1.disabled); True
in1.disabled = false; Cancel disabled
Console.log (in1.disabled); False
Console.log (In1.getattribute (' disabled ')); The disabled has been removed from the null,attribute.

Or:

Console.log (in1.disabled); True
In1.removeattribute (' disabled '); Remove the disabled from the attribute to cancel the Disable
Console.log (in1.disabled); False
Console.log (In1.getattribute (' disabled ')); The disabled has been removed from the null,attribute.

You can find that setting the disabled in the property to False removes the disabled in the attributes. So the data binding becomes,property<=>attribute; again.

Therefore, the data binding problem between property and Attritude can not be explained simply by "Property<-attribute".


Summarize

With so much analysis, the distinction between property and attribute is deeper, and here's a summary:


Create





The default basic property is created when the DOM object is initialized;


Only attributes defined in the HTML tag are stored in the property's attributes attribute;


Attribute initializes the property with the same name, but custom attributes do not appear in the properties;


The value of attribute is a string;





Data Binding





Attributes data will be synchronized to the property, but the property changes will not change the attribute;


For properties/attributes such as Value,class, the direction of data binding is one-way,attribute-&gt;property;


For IDs, data binding is bi-directional,attribute&lt;=&gt;property;


For disabled, the property on the disabled is false, attribute on the disabled must be and exist, at this time data binding can be considered two-way;





Use





You can use the SetAttribute method of Dom to change attribute at the same time;


Direct access to the value on the attributes will get a attr object, while access through the GetAttribute method will directly get the attribute value;


In most cases (unless there is a browser compatibility issue), Jquery.attr is implemented through setattribute, while Jquery.prop accesses the property of the DOM object directly;





So far, the property is the attribute that the DOM object itself has, and attribute is the attribute that we assign to it by setting the HTML tag, and there are some special data links between attributes and property/attributes of the same name. These links can be different for different attributes/attributes.





In fact, here, the distinction and connection between property and attribute is difficult to describe with simple technical features, and I find the following answer on the Stackflow, or closer to the real answer:





These words existed way before Computer came of science around.





attribute is a quality or object so we to someone or something. For example, the scepter was an attribute of power and statehood.





The property is a quality which exists without any attribution. For example, clay has adhesive qualities; Or, one of the properties of metals is electrical conductivity. Properties demonstrate themselves though physical phenomena without the need attribute them to someone or something. By the same token, saying this someone has masculine is attributes. In effect, your could say that's a property was owned by someone or something.





To is fair though, in Computer, two words, at least for the most part, can is used Interchangeably-but Again programmers usually don ' t hold degrees in Chinese literature and do not write or care more about grammar books:).





The two most critical words:





attribute is the trait or object that we give to something.


Property (attribute) is a pre-existing trait that does not need to be endowed by the outside world.



a detailed introduction to the difference between property and attribute in JavaScript





1. Define





Property: Properties, all HTML elements are represented by the HtmlElement type, the HtmlElement type directly inherits from the element and adds some attributes, which correspond to the following 5 standard attributes for each HTML element: ID, Title,lang,dir,classname. A DOM node is an object, so he can add custom properties and methods like other JavaScript objects. The value of the property can be any data type, sensitivity to case sensitive, custom property will not appear in the HTML code, only JS.





attribute: characteristics, different from Property,attribute can only be strings, case insensitive, appear in the innerHTML, through the class array attributes can list all the attribute.





2. The same place





The standard DOM properties are synchronized with the attributes. Recognized (not customizable) attributes are added to the DOM object as attributes. such as Id,align,style and so on, the Operation property or the DOM method that uses the operation characteristic such as getattribute () can manipulate the attribute. However, the attribute name passed to GetAttribute () is the same as the actual attribute name. So when you get the attribute value of class, you pass in "class".





3. The difference





1. For the operation of some standard characteristic, getattribute and dot number (.) The value obtained has a difference. such as Href,src,value,style,onclick, such as event handlers.


2. Href:getattribute gets the actual value of the href, and the dot gets the full URL, and there is a browser difference.








The code is as follows:





&lt;script&gt;


var a = document.body.children[0]


A.href = '/'


Alert (' attribute: ' + a.getattribute (' href ') ')//'/'


Alert (' property: ' + a.href ')//IE: '/', Others:full URL


&lt;/script&gt;











The value of SRC is obtained like an href, but IE also returns a full URL;


The value value also has built-in properties for some ' one-way ' (one-way) synchronization.


For example, Input.value is synchronized from attribute (that is, the property is synchronized from attribute)








The code is as follows:





&lt;input type= "text" value= "Markup" &gt;


&lt;script&gt;


var input = document.body.children[0];


Input.setattribute (' Value ', ' new ');


alert (Input.value); ' New ', Input.value changed


Alert (Input.getatrribute (value)); ' New '


&lt;/script&gt;











But attribute cannot be synchronized from the property:


The code is as follows:





&lt;input type= "text" value= "Markup" &gt;


&lt;script&gt;


var input = document.body.children[0];


Input.value = ' new ';


Alert (Input.getattribute (' value ')); ' Markup ', not changed!


&lt;/script&gt;











GetAttribute Gets the initial value, and the dot gets the initial value or the modified value of. Value, for example, when a visitor enters certain characters, the ' value ' attribute maintains the original value after the property has been updated. The original value can be used to verify that input is changing or to reset it.





For event handlers such as style and OnClick, a string is returned when the GetAttribute method accesses, and the point number returns the corresponding object and event handler function.





For the checked property in input


The code is as follows:





&lt;script&gt;


var input = document.body.children[0]


Alert (input.checked)//True


Alert (Input.getattribute (' checked '))//empty string


&lt;/script&gt;





GetAttribute Gets the value that you are actually setting. And the point number returns a Boolean value.





Differences in Browser compatibility





1. In ie&lt;9 browsers, you can access custom properties between each other using dots and getattribute.


2.ie&lt;8 (including the IE7 compatibility mode of IE8), the property and attribute are the same. Because attribute is not sensitive to case, in this case, the browser will choose the first occurrence of the value when using GetAttribute to access the feature.





The code is as follows:





Document.body.abba = 1//Assign property (now can read it by GetAttribute)


Document.body.ABBA = 5//Assign property with another case


Must get a property named ' ABba ' in case-insensitive way.


Alert (Document.body.getAttribute (' ABba '))//1








Priority Selection Property





In practical applications, 98% of DOM operations are using properties.


Only two scenarios require the use of attributes





1. Customize the HTML attributes because it is not synchronized to the DOM property.


2. Access to the built-in HTML attributes, these attributes cannot be synchronized from the property. such as the value of the input label.


Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.