在一些框架和库中都可见到一些创建一个空元素,通过对该元素特性测试来判定当前运行环境是否支持某种特性的运用。jQuery 也是以此来 support 各种环境,与其通过可被随意修改的 UA 测试环境倒不如直接创建元素测试来的准确。

我们可利用元素本身特性去做的事并不止于 特性测试。细心一点,你会发现一些元素独一无二的特性可以被巧妙利用来做一些工作。

HTML转义

创建 Option 实例,传入要被转义的字符串。因为 Option 构造函数第一个参数为 text,所以任你传入任何 html 代码都会被转义为 textNode

new Option('<div></div>').innerHTML // "&lt;div&gt;&lt;/div&gt;"

同理,给 divinnerText 赋值,再通过 innerHTML 取,也可以做到,只是看起来不如一行代码来的巧妙。

var div = document.createElement('div');
div.innerText = '<a></a>';
console.log(div.innerHTML) // "&lt;a&gt;&lt;/a&gt;"

解析URL

a 标签天生支持这些 URL 属性,是不是像极了 NodeJS 中 URL 对象。

var a = document.createElement('a');
a.href = 'http://test.com:3000/a/b?k=1#dd';
console.log(a.protocol); // "http:"
console.log(a.host); // "test.com"
console.log(a.hostname) // "test.com"
console.log(a.port) // 3000
console.log(a.pathname) // "/a/b"
console.log(a.search) // "?k=1"
console.log(a.hash) // "#dd"

获取一串文字在浏览器中所占的宽度

想知道宽度还不简单,扔到浏览器中跑一圈看看。

var tester = document.createElement('div');
tester.style.display = 'inline-block';
tester.innerHTML = '博客:imys.net';
document.body.appendChild(tester);
console.log(tester.offsetWidth)

display 属性一定要设置为 inline-block。因为 div:display 默认为 block,块级元素宽度默认等于父级元素宽度,这样获取到的宽度就不是字符的宽度了。

当你想用 js 去截断一段长文字时,可以使用这个例子。

判断canvas是否为空

两个等宽等高内容相同的 canvas 所生成的 dataURL 是相同的,这样最终把对象的比较转换为字符串的比较。

function isCanvasBlank(canvas) {
var blank = document.createElement('canvas');
blank.width = canvas.width;
blank.height = canvas.height;
return canvas.toDataURL() === blank.toDataURL();
}

获取Computed styles

这里的 Computed styles 不是指 getComputedStyle(element) 函数结果,而是像浏览器 Dev Tools 中 Styles 面板右侧的计算样式。是要获取最终被样式表影响的 css 属性,不包括标签默认属性和 user agent stylesheet

function filterInheritedStyles(el){
var tester = document.createElement(el.tagName);
document.body.appendChild(tester); // 元素必须插入到文档中才能计算出默认样式
var defaultStyle = window.getComputedStyle(tester, null);
var currentStyle = window.getComputedStyle(el, null);
var ret = {};
for(var k in currentStyle) {
if(currentStyle.getPropertyValue(k) !== defaultStyle.getPropertyValue(k)) {
ret[k] = currentStyle.getPropertyValue(k);
}
}
document.body.removeChild(tester);
return ret;
}

创建一个标签相同的 Element 添加到文档中产生默认样式,与当前元素样式逐个比较,返回不一致的样式属性。

不过这个函数还不是最终版的。当一个元素被插入到文档中时,由于没有添加 id 、 class 、style 属性,也就不会受 id 选择器、类选择器、行内样式影响,但显然会受标签选择器影响。

所以如果能在返回值基础上对标签选择器属性进行过滤,才是最终结果。但目前通过 document.styleSheets 只限于获取内联样式表中规则,对于外部样式表中的规则检索还没有什么好的办法。


暂时只知道这么多。针对前端复杂的客户环境,单就 特性测试 而言已经可以帮我们解决很多问题了。