javascript功能_Javascript中缺少的五个有用功能

javascript功能

JavaScript已经存在了好几年,它的核心也在不断成熟,其中包括可以帮助程序员完成工作的新类和函数。 但是,仍然缺少一些基本的实用程序功能,而是使用jQueryPrototypeMooTools之类的库来实现。 使用这些工具很棒,但是在某些情况下,对于您的需求而言,过度使用它们是不行的。 本文涵盖了我一直认为属于JavaScript的五个有用函数。

getElementsByClassName()

JavaScript允许使用带有getElementById()函数的id检索元素,但是在HTML5之前,没有本机函数使用类名来获取一个或多个元素。 新功能称为getElementsByClassName() ,在Firefox 3 +,Opera 9.5 +,Safari 3.1+和所有版本的Google Chrome中都可用。 不幸的是,您可能会猜到,并非所有版本的Internet Explorer都可用,Internet Explorer是Web设计人员的头号敌人浏览器。 仅Internet Explorer 9+支持getElementsByClassName() ,因此对于较旧的版本,您需要包装函数。

我发现最好的功能是由Robert Nyman编写的。 他的实现是根据MIT许可发布的,并且已由WHATWG推荐它在支持它的浏览器中使用本机的getElementsByClassName()方法,然后回退到鲜为人知的document.evaluate()方法,较早版本的Firefox(至少1.5版本)和Opera(至少9.27版本document.evaluate()都支持该方法。 )。 如果所有其他方法均失败,则脚本将退回以递归地遍历DOM并收集与给定类名匹配的元素 。 您可以在下面及其存储库中找到代码。

var getElementsByClassName = function (className, tag, elm){
  if (document.getElementsByClassName) {
    getElementsByClassName = function (className, tag, elm) {
      elm = elm || document;
      var elements = elm.getElementsByClassName(className),
      nodeName = (tag)? new RegExp("\b" + tag + "\b", "i") : null,
      returnElements = [],
      current;
      for(var i=0, il=elements.length; i<il; i+=1){
        current = elements[i];
        if(!nodeName || nodeName.test(current.nodeName)) {
          returnElements.push(current);
        }
      }
      return returnElements;
    };
  }
  else if (document.evaluate) {
    getElementsByClassName = function (className, tag, elm) {
      tag = tag || "*";
      elm = elm || document;
      var classes = className.split(" "),
      classesToCheck = "",
      xhtmlNamespace = "http://www.w3.org/1999/xhtml",
      namespaceResolver = (document.documentElement.namespaceURI === xhtmlNamespace)? xhtmlNamespace : null,
                           returnElements = [], elements, node;
      for(var j=0, jl=classes.length; j<jl; j+=1){
        classesToCheck += "[contains(concat(' ', @class, ' '), ' " + classes[j] + " ')]";
      }
      try {
        elements = document.evaluate(".//" + tag + classesToCheck, elm, namespaceResolver, 0, null);
      }
      catch (e) {
        elements = document.evaluate(".//" + tag + classesToCheck, elm, null, 0, null);
      }
      while ((node = elements.iterateNext())) {
        returnElements.push(node);
      }
      return returnElements;
    };
  }
  else {
    getElementsByClassName = function (className, tag, elm) {
      tag = tag || "*";
      elm = elm || document;
      var classes = className.split(" "),
          classesToCheck = [],
          elements = (tag === "*" && elm.all)? elm.all : elm.getElementsByTagName(tag),
          current,
          returnElements = [],
          match;
      for(var k=0, kl=classes.length; k<kl; k+=1){
        classesToCheck.push(new RegExp("(^|\s)" + classes[k] + "(\s|$)"));
      }
      for(var l=0, ll=elements.length; l<ll; l+=1){
        current = elements[l];
        match = false;
        for(var m=0, ml=classesToCheck.length; m<ml; m+=1){
          match = classesToCheck[m].test(current.className);
          if (!match) {
            break;
          }
        }
        if (match) {
          returnElements.push(current);
        }
      }
      return returnElements;
    };
  }
  return getElementsByClassName(className, tag, elm);
};

延伸()

如果您曾经编写过插件,则几乎可以肯定会遇到合并两个或更多对象的问题。 当您具有一些默认设置并希望用户能够替换某些默认值时,通常会发生这种情况。 如果使用的是jQuery,则可以使用extend() ,但是由于我们在谈论原始JavaScript,所以坏消息是没有本机函数。 幸运的是,您可以轻松地自己构建它。 下面的示例将向您展示如何创建与jQuery方法相同的代码。 我将extend()方法添加到Object原型,以便所有对象可以共享同一方法。

Object.prototype.extend = function() {
  if (arguments.length === 0)
    return this;

  for (var i = 0; i < arguments.length; i++) {
    for (var property in arguments[i]) {
      if (arguments[i].hasOwnProperty(property))
        this[property] = arguments[i][property];
    }
  }
  return this;
};

此函数接受可变数量的参数。 这可以通过使用arguments来实现, arguments是每个函数内部可用的局部数组状对象。 如果您需要有关arguments更多信息,我建议您阅读参数:A JavaScript Oddity

等于()

对象比较是非常常见的操作。 尽管可以使用严格相等运算符( === )完成此测试,但是有时您不想测试两个变量是否引用内存中的同一对象。 相反,您想知道两个对象是否具有具有相同值的相同属性。 下面的代码正是这样做的。 请注意,以下代码不是我的; 它属于一个名为crazyx的用户。 同样, equals()已添加到Object.prototype

Object.prototype.equals = function(x) {
  var p;
  for(p in this) {
    if (typeof(x[p]) == "undefined")
      return false;
  }
  for(p in this) {
    if (this[p]) {
      switch(typeof(this[p])) {
        case "object":
          if (!this[p].equals(x[p]))
            return false;
          break;
        case "function":
          if (typeof(x[p]) == "undefined" ||
             (p != "equals" && this[p].toString() != x[p].toString()))
            return false;
          break;
        default:
          if (this[p] != x[p])
            return false;
      }
    }
    else {
      if (x[p])
        return false;
    }
  }
  for(p in x) {
    if(typeof(this[p])=="undefined")
      return false;
  }
  return true;
}

inArray()

JavaScript没有本机方法来测试值是否在数组中。 如您所料,我们将编写一个函数,如果该值存在,该函数将返回true ,否则返回false 。 此函数只是将给定值与数组的每个元素进行身份比较。 就像前两个示例一样,将inArray()添加到Array类的prototype属性中。

Array.prototype.inArray = function (value) {
  for (var i = 0; i < this.length; i++) {
    if (this[i] === value)
      return true;
  }
  return false;
};

由于功能简单,因此在许多情况下无法正常工作。 尽管它对于诸如StringNumbers类的基本类型都适用,但是如果您比较对象,则仅在函数找到相同对象时返回true 。 为了更好地理解它是如何工作的,让我们看下面的示例。

var array = [1, 2, 3];
console.log(array.inArray(2)); // print true

var obj = {"prop": "value"};
array = [{"prop": 1}, {"prop": "a long string"}, {"prop": "value"}];
console.log(array.inArray(obj)); // print false, not true as you might expect

array = [{"prop": 1}, {"prop": "a long string"}, obj];
console.log(array.inArray(obj)); // print true

可以使用前面讨论的equals()函数来增强提供的功能。 这样,如果两个对象具有相同的属性和值,我们就可以进行匹配。 我们可以做的另一项改进是使函数返回元素的位置,而不是简单地返回truefalse 。 该功能的最终版本如下所示。

Array.prototype.inArray = function (value) {
  for (var i = 0; i < this.length; i++) {
    if (typeof value === "object") {
      // If both are objects, uses the equals function
      if (typeof this[i] === "object" && value.equals(this[i]))
          return i;
    }
    else if (this[i] === value)
      return i;
  }
  return false;
};

现在,如果再次运行以上示例,您将获得:

1
2
2

toggleClass()

jQuery中经常使用的另一种方法是toggleClass() 。 它根据元素的名称是否存在,从元素中添加或删除元素。 下面显示了toggleClass()简单版本。

function toggleClass(id, className) {
  var element = document.getElementById(id);
  var classes = element.className.split(/s+/);
  var length = classes.length;

  for(var i = 0; i < length; i++) {
    if (classes[i] === className) {
      classes.splice(i, 1);
      break;
    }
  }
  // The className is not found
  if (length === classes.length)
    classes.push(className);

  element.className = classes.join(" ");
}

此代码也可以进行改进。 函数中的for循环只搜索classes数组。 我们可以通过调用inArray()函数来替换循环,从而产生以下代码。

function toggleClass(id, className) {
  var element = document.getElementById(id);
  var classes = element.className.split(/s+/);
  var length = classes.length;
  var found = classes.inArray(className);
  if (found !== false)
    classes.splice(found, 1);
  // The className is not found
  if (length === classes.length)
    classes.push(className);
  element.className = classes.join(" ");
}

结论

本文重点介绍了我认为JavaScript缺少的一些最重要的功能。 当然,JavaScript会遗漏其他内容,我们将在下周看到。 但是,现在,我想指出以下几点:

  • jQuery之类的框架具有许多有用的功能,但它们增加了开销。 因此,如果您只需要几个函数,请使用原始JavaScript并将所需的方法分组在一个扩展文件中。
  • 如果您使用的是新JavaScript版本中引入的功能,请不要忽略它。 使用条件语句包装它以测试是否受支持,如果不支持,请使用针对getElementsByClassName()指出的旧代码。 这样,您将继续支持旧的浏览器。
  • 如可能,将函数添加到对象的原型,如extend()所示。 所有实例将共享相同的方法,您将获得更好的性能。
  • 如有可能,请按第二个版本的toggleClass()重复使用您的代码。

翻译自: https://www.sitepoint.com/5-useful-functions-missing-in-javascript/

javascript功能

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值