你认为每个程序员都应该知道JavaScript的哪些“隐藏特性”?

在看到以下问题的优质答案后,我认为是时候向JavaScript请求它了。

HTML的隐藏特性 CSS的隐藏特性 PHP的隐藏特性 ASP的隐藏特性。网 c#的隐藏特性 Java的隐藏特性 Python的隐藏特性

尽管JavaScript可以说是目前最重要的客户端语言(问问谷歌就知道了),但令人惊讶的是,大多数web开发人员很少意识到它的强大。


当前回答

合并操作符非常酷,可以生成一些干净简洁的代码,特别是当你将它们链接在一起时:a || b || c ||“default”;问题是,由于它是通过计算为bool而不是null来工作的,如果计算为false的值是有效的,它们通常会被忽略。不用担心,在这些情况下,只要恢复到好的三元操作符就可以了。

我经常看到代码已经放弃使用全局变量而不是静态变量,所以下面是如何(在一个我认为你可以称之为泛型单例工厂的例子中):

var getInstance = function(objectName) {
  if ( !getInstance.instances ) {
    getInstance.instances = {};
  }

  if ( !getInstance.instances[objectName] ) {
    getInstance.instances[objectName] = new window[objectName];
  }

  return getInstance.instances[objectName];
};

另外,请注意新窗口[objectName];这是通过名称一般实例化对象的关键。我两个月前才算出来的。

本着同样的精神,在使用DOM时,当我第一次初始化我要添加的任何功能时,我经常将功能参数和/或标志埋藏在DOM节点中。如果有人抱怨,我再举个例子。

令人惊讶的是,第一页上没有人提到hasOwnProperty,这是一个遗憾。当使用in进行迭代时,在迭代的容器上使用hasOwnProperty方法以确保所使用的成员名是您所期望的成员名,这是一种很好的防御性编程。

var x = [1,2,3];
for ( i in x ) {
    if ( !x.hasOwnProperty(i) )  { continue; }
    console.log(i, x[i]);
}

阅读这里了解更多。

最后,with几乎总是一个坏主意。

其他回答

你可以在任何对象上执行一个对象的方法,不管它是否有这个方法。当然,它可能并不总是有效(如果方法假设对象具有它没有的东西),但它可能非常有用。例如:

function(){
    arguments.push('foo') // This errors, arguments is not a proper array and has no push method
    Array.prototype.push.apply(arguments, ['foo']) // Works!
}

函数语句和函数表达式的处理方式不同。

function blarg(a) {return a;} // statement
bleep = function(b) {return b;} //expression

所有函数语句在代码运行之前都会被解析——JavaScript文件底部的函数将在第一个语句中可用。另一方面,它将无法利用某些动态上下文,例如围绕语句—在解析函数时,with还没有执行。

函数表达式在遇到它们的地方内联执行。在此之前它们是不可用的,但它们可以利用动态上下文。

在这个帖子中有几个答案告诉你如何去做 通过Array对象的原型扩展Array对象。这很糟糕 IDEA,因为它破坏了语句中的for (i)。

如果你不使用for (i in a) 代码中的任何地方?除非你自己的代码是 只有您正在运行的代码,这是不太可能的 在浏览器内部。我担心如果人们开始扩张 他们的数组对象像这样,堆栈溢出将启动 充斥着一堆神秘的JavaScript错误。

点击这里查看有用的细节。

这是jQuery的一个隐藏特性,而不是Javascript,但因为永远不会有“jQuery的隐藏特性”的问题……

你可以在jQuery中定义自己的:something选择器:

$.extend($.expr[':'], {
  foo: function(node, index, args, stack) {
    // decide if selectors matches node, return true or false
  }
});

对于使用:foo的选择,例如$('div.block:foo("bar,baz") span'),函数foo将被用于匹配选择器中已经处理的部分的所有节点。论证的意义:

node holds the current node index is the index of the node in the node set args is an array that is useful if the selector has an argument or multiple names: args[0] is the whole selector text (e.g. :foo("bar, baz")) args[1] is the selector name (e.g. foo) args[2] is the quote character used to wrap the argument (e.g. " for :foo("bar, baz")) or an empty string if there is no quoting (:foo(bar, baz)) or undefined if there is no argument args[3] is the argument, including any quotes, (e.g. "bar, baz") or undefined if there are no arguments stack is the node set (an array holding all nodes which are matched at that point)

如果选择器匹配,函数将返回true,否则返回false。

例如,下面的代码将支持基于全文regexp搜索选择节点:

$.extend($.expr[':'], {
  matches: function(node, index, args, stack) {
    if (!args.re) { // args is a good place for caching
      var re = args[3];
      if (args[2]) { // get rid of quotes
        re = re.slice(1,-1);
      }
      var separator = re[0];
      var pos = re.lastIndexOf(separator);
      var modifiers = re.substr(pos+1);
      var code = re.substr(1, pos-1);
      args.re = new RegExp(code, modifiers);
    }
    return $(node).text().match(args.re);
  }
});

// find the answers on this page which contain /**/-style comments
$('.answer .post-text code:matches(!/\\*[\\s\\S]*\\*/!)');

使用.filter()的回调版本也可以达到类似的效果,但自定义选择器要灵活得多,通常可读性也更好。

合并操作符非常酷,可以生成一些干净简洁的代码,特别是当你将它们链接在一起时:a || b || c ||“default”;问题是,由于它是通过计算为bool而不是null来工作的,如果计算为false的值是有效的,它们通常会被忽略。不用担心,在这些情况下,只要恢复到好的三元操作符就可以了。

我经常看到代码已经放弃使用全局变量而不是静态变量,所以下面是如何(在一个我认为你可以称之为泛型单例工厂的例子中):

var getInstance = function(objectName) {
  if ( !getInstance.instances ) {
    getInstance.instances = {};
  }

  if ( !getInstance.instances[objectName] ) {
    getInstance.instances[objectName] = new window[objectName];
  }

  return getInstance.instances[objectName];
};

另外,请注意新窗口[objectName];这是通过名称一般实例化对象的关键。我两个月前才算出来的。

本着同样的精神,在使用DOM时,当我第一次初始化我要添加的任何功能时,我经常将功能参数和/或标志埋藏在DOM节点中。如果有人抱怨,我再举个例子。

令人惊讶的是,第一页上没有人提到hasOwnProperty,这是一个遗憾。当使用in进行迭代时,在迭代的容器上使用hasOwnProperty方法以确保所使用的成员名是您所期望的成员名,这是一种很好的防御性编程。

var x = [1,2,3];
for ( i in x ) {
    if ( !x.hasOwnProperty(i) )  { continue; }
    console.log(i, x[i]);
}

阅读这里了解更多。

最后,with几乎总是一个坏主意。