javascript功能
JavaScript已经存在了好几年,它的核心也在不断成熟,其中包括可以帮助程序员完成工作的新类和函数。 但是,仍然缺少一些基本的实用程序功能,而是使用jQuery , Prototype和MooTools之类的库来实现。 使用这些工具很棒,但是在某些情况下,对于您的需求而言,过度使用它们是不行的。 本文涵盖了我一直认为属于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;
};
由于功能简单,因此在许多情况下无法正常工作。 尽管它对于诸如String
和Numbers
类的基本类型都适用,但是如果您比较对象,则仅在函数找到相同对象时返回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()
函数来增强提供的功能。 这样,如果两个对象具有相同的属性和值,我们就可以进行匹配。 我们可以做的另一项改进是使函数返回元素的位置,而不是简单地返回true
或false
。 该功能的最终版本如下所示。
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功能