Which is the correct or better way to create a new

2019-03-15 11:22发布

Related to the answer https://stackoverflow.com/a/10619477/1076753 to cleate an element is better to use

$("<div>", {id: "foo", class: "a"});

or

$("<div />", {id: "foo", class: "a"});

They both works, but which is better or correct to use?

The official API Documentation says that to ensure cross-platform compatibility, the snippet must be well-formed. Tags that can contain other elements should be paired with a closing tag:

$( "<a href='http://jquery.com'></a>" );

while Tags that cannot contain elements may be quick-closed or not:

$( "<img>" );
$( "<input>" );

So, at the end it's wrong to use one of the first two options for a div?

4条回答
劫难
2楼-- · 2019-03-15 12:01

taking a look into the jQuery library, the following is the relevant section from v2.2.0 line 2827.

init = jQuery.fn.init = function(selector, context, root) {
    var match, elem;

    // HANDLE: $(""), $(null), $(undefined), $(false)
    if (!selector) {
      return this;
    }

    // Method init() accepts an alternate rootjQuery
    // so migrate can support jQuery.sub (gh-2101)
    root = root || rootjQuery;

    // Handle HTML strings
    if (typeof selector === "string") {
      if (selector[0] === "<" &&
        selector[selector.length - 1] === ">" &&
        selector.length >= 3) {

        // Assume that strings that start and end with <> are HTML and skip the regex check
        match = [null, selector, null];

      } else {
        match = rquickExpr.exec(selector);
      }

      // Match html or make sure no context is specified for #id
      if (match && (match[1] || !context)) {

        // HANDLE: $(html) -> $(array)
        if (match[1]) {
          context = context instanceof jQuery ? context[0] : context;

          // Option to run scripts is true for back-compat
          // Intentionally let the error be thrown if parseHTML is not present
          jQuery.merge(this, jQuery.parseHTML(
            match[1],
            context && context.nodeType ? context.ownerDocument || context : document,
            true
          ));

          // HANDLE: $(html, props)
          if (rsingleTag.test(match[1]) && jQuery.isPlainObject(context)) {
            for (match in context) {

              // Properties of context are called as methods if possible
              if (jQuery.isFunction(this[match])) {
                this[match](context[match]);

                // ...and otherwise set as attributes
              } else {
                this.attr(match, context[match]);
              }
            }
          }

          return this;

You will see that it checks if the selector is a string, and if it does then see's if it starts with < and ends with >.

if (typeof selector === "string") {
  if (selector[0] === "<" &&
    selector[selector.length - 1] === ">" &&
    selector.length >= 3) {

Then, having in mind the regex rsingleTag being:-

var rsingleTag = ( /^<([\w-]+)\s*\/?>(?:<\/\1>|)$/ );

Which matches both "<div>" and "<div />", returning div as group[1].

The parseHTML uses that to return a div element, in the merge:-

jQuery.parseHTML = function( data, context, keepScripts ) {

    ...

    var parsed = rsingleTag.exec( data );

    // Single tag
    if ( parsed ) {
        return [ context.createElement( parsed[ 1 ] ) ];
    }

then using the regex again, and context as your object for setting the properties:-

// HANDLE: $(html, props)
if (rsingleTag.test(match[1]) && jQuery.isPlainObject(context)) {

it for's over each property setting with this.attr(match, context[match]);

So, at the end it's wrong to use one of the first two options for a div?

As above shows, its personal preference. Both work the same.

查看更多
Animai°情兽
3楼-- · 2019-03-15 12:19

If you go solely by metrics that can be easily measured: The first is better because it is 2 bytes shorter.

Once you start accounting for readability and other less tangible considerations, it becomes largely a matter of opinion.

So, at the end it's wrong to use one of the first two options for a div?

No, that section only applies "If the HTML is more complex than a single tag without attributes"

查看更多
做个烂人
4楼-- · 2019-03-15 12:19

From jQuerys website:

It makes things like HTML document traversal and manipulation, event handling, animation, and Ajax much simpler..

Notice that it doesn't mention HTML generation.

JavaScript provides the document.createElement method. jQuery utilizes this method if HTML-like string is passed as the selector.

The jQuery entry point ($(whatEverIFeelLikeDoingToday)) type checks the selector for string, node or function, then handles the request accordingly. If the argument is string, it then passes through +/- 60 lines of code (Am I HTML? Am I a selector, am I an ID, am I a class?). After the HTML-like string is identified, it is then passed to another function (additional function calls) to be generated -therefore slow (see benchmark below). In fact, it doesn't add much value to the process, aside from uniformity, just slows it down.

I've found the best practice to be: not using jQuery for rather simple tasks (i.e. node creation) -wherever practice, eliminate the obstacles in it's way.

var div = document.createElement('div');
div.setAttribute("id", "foo");
div.setAttribute("class", "a");
div = $(div);

Notice the significant performance increase in this benchmark. (Just about 4x faster in Chrome). This solution is Faster than the two described above and inherently Cross platform.

I don't think that the argument for less bytes -vs faster execution time is in the scope of this thread. However, assuming you are minifying your code, I will throw out a the practical example of looping through an array to generate html rows for a table. Bytes aren't the problem, you only needed to load the script once -execution is what bogs you down.

查看更多
Evening l夕情丶
5楼-- · 2019-03-15 12:27

With better or correct use in your case it depends on how frequently this code will appear in your page. @Quentin is correct in that there is only a two byte difference between the first and second option. Now if the code only appears a few times in the whole page then realistically unless you are recording a large amount of traffic on your server you will not see a significant difference between the two, on the other hand if you are running a medium to high traffic site or will be having a large number of instances of this javascript appearing on your page then the best option would be to go with option one as it is two bytes smaller and over a larger page with many instances of this code you will find measurable savings in the byte size of the page.

As for well formed tags for cross platform compatibility both the first and second options will result in the exact same end result in the browser so in your use case compatibility will not be affected by either option.

Based on these points I would suggest using option one as it provides the two byte advantage over option two, that is effectively the only difference between the two options in your use case.

查看更多
登录 后发表回答