IE下获取链接相对路径的问题

1
<a href="about.html" id="anc">a link with href="about.html"</a>
1
2
3
4
var anchor = document.getElementById('anc');

console.log(anchor.href);
console.log(anchor.getAttribute('href'));

以上代码,对于第一个 log,希望得到形如 http://liunian.info/about.html 的绝对路径,对于第二个 log,希望得到 about.html 这个相对路径。

但在 ie 下,第二个却也由相对路径变为绝对路径了。

兼容的处理方法是使用第二个参数,这个参数是 IE 私有的,但由于 JavaScript 的语言特性,多参数并不会导致出错,所以,对于 Chrome、FF 等将仍是原来的方法。

1
anchor.getAttribute('href', 2);

References

  1. getAttribute(“HREF”) is always absolute
  2. 获得原始href属性的方法
  3. getAttribute method

JavaScript生成指定范围内的随机数

JavaScript 中,可以使用 Math.random() 来获得 [0, 1) 之间的随机数,但没有直接的获取一给定范围内的随机数,出于使用频率还算多,可以写成一个函数。

JavaScript 中,可以使用 Math.random() 来获得 [0, 1) 之间的随机数,但没有直接的获取一给定范围内的随机数,出于使用频率还算多,可以写成一个函数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// mod from: http://roshanbh.com.np/2008/09/get-random-number-range-two-numbers-javascript.html

function randomToN(maxVal, floatVal) {
    var randVal = Math.random() * maxVal;
    return typeof floatVal === 'undefined' ?
        Math.floor(randVal) : randVal.toFixed(floatVal);
}

function randomXToY(minVal, maxVal, floatVal) {
    var randVal = minVal + Math.random() * (maxVal - minVal);
    return typeof randVal === 'undefined' ?
        Math.floor(randVal) : randVal.toFixed(floatVal);
}

// example usages:
randomToN(50);           // => 35
randomToN(50, 3);        // => 37.748
randomXToY(30, 80);      // => 51
randomXToY(30, 80, 2);   // => 68.36

JavaScript 之 String.replace

最简单的用法

直接的用字符串替换字符串是最简单的用法,这种情况下将只会替换掉第一个匹配的字符串。

1
var res = 'a1a2a3'.replace('a', 'b'); // => 'b1a2a3'

使用正则来达到复杂的要求

JavaScript 中正则的介绍可参照 MDN 的 RegExp

1
2
3
4
// 把字符串的所有英文字符都去掉,不论大小写
var pattern = /[a-z]/gi;
var str = '1aBc2d3E4f5e';
var res = str.replace(pattern, ''); // => '12345'

继续阅读“JavaScript 之 String.replace”

把JavaScript中的伪数组转换为真数组

在 JavaScript 中, 函数中的隐藏变量 arguments 和用 getElementsByTagName 获得的元素集合(NodeList)都不是真正的数组,不能使用 push 等方法,在有这种需要的时候只能先转换为真正的数组。arguments 可以使用 Array.prototype.slice.call 来转换,但在 ie8 及以下,此方法对 NodeList 无效,所以需要循环来实现。

在 JavaScript 中, 函数中的隐藏变量 arguments 和用 getElementsByTagName 获得的元素集合(NodeList)都不是真正的数组,不能使用 push 等方法,在有这种需要的时候只能先转换为真正的数组。

对于 arguments,可以使用 Array.prototype.slice.call(arguments); 来达到转换的目的,但对于 NodeList 则不行了,其在 IE8 及以下将会报错,只能说其 JS 引擎有所限制。

因此,如果需要把 NodeList 转换为真正的数组,则需要做下兼容处理。

1
2
3
4
5
6
7
8
9
10
11
function realArray(c) {
    try {
        return Array.prototype.slice.call(c);
    } catch (e) {
        var ret = [], i = 0, len = c.length;
        for (; i < len; i++) {
            ret[i] = (c[i]);
        }
        return ret;
    }
}

References

  1. javascript Array.prototype.slice使用说明
  2. Advanced Javascript: Objects, Arrays, and Array-Like objects

代价的选择

对于语言来说,如果想减少跨平台开发的消耗,那么就要付出语言运行效率的代价。比如java等依赖于虚拟机的语言,很大程度上是一次编译处处运行的,但效率上就远远哪不上c这种可以直接和硬件打交道的语言。

javascript这种解释性的语言则更是跨平台,只要浏览器依照了规范,那么就处处可以运行,但效率上就更慢上一些了。再加上其天然的单线程特征,在处理复杂运动上就更加劣势了。

touchpad 的概念不说不好,但由于采用语言本身的问题,比采用 java 的android慢上很多,更不用说是采用object-c的ios了。

JavaScript保留字

JavaScript 除了语言规范本身的关键字、保留字外,在和浏览器结合的过程中产生了更多的保留字,有一次就踩中了status这个雷区,故特意找来一下这方面的资料[1]以备忘。

JavaScript Reserved Words
break continue do for import new this void
case default else function in return typeof while
comment delete export if label switch var with

继续阅读“JavaScript保留字”

连续赋值与求值顺序

看到一个2010 年的帖子[1],里面讨论了一段 JavaScript 代码:

1
2
3
var a = {n:1};
a.x = a = {n:2};  
alert(a.x);     // --> undefined

帖子里有很多的讨论来分析为何 a.xundefined,下面是我的一些思考。

首先,在JavaScript中,有以下几点需要明确的:

  1. 可以说一切都是对象,一切都是引用调用。
  2. 赋值运算符(=)是除逗号运算符(,)外优先级最低的,并且是右结合的。[2]
  3. 求值顺序[3]是从左向右的[4]

继续阅读“连续赋值与求值顺序”

鼠标滚轮缩放图片

浏览网页的时候,有时候图片局限于网站而很小,即便原来是一张大图。为了偷懒不想新标签页打开图片,于是写了个小小的 bookmarklet 来直接在图片上通过鼠标滚轮来进行缩放。

1
javascript:(function(){var imgs=document.getElementsByTagName('img');var rate=rate||0.1;for(var j=0,l=imgs.length;j<l ;j++){(function(i){var item=imgs[i];item.onmousewheel=function(e){e=e||window.event;zoom(imgs[i],mouseWheelRes(e),rate);};if(item.addEventListener){item.addEventListener('DOMMouseScroll',function(e){zoom(imgs[i],mouseWheelRes(e),-rate);},false);}})(j);}function zoom(img,inOut,rate){if(inOut>0){img.width=img.width*(1+rate);img.height=img.height*(1+rate);}else{img.width=img.width*(1-rate);img.height=img.height*(1-rate);}}function mouseWheelRes(e){e.preventDefault?e.preventDefault():e.returnValue=false;e.stopPropagation?e.stopPropagation():e.cancelBubble=true;return e.wheelDelta||e.detail;}})();

可读性良好一些的代码如下:
继续阅读“鼠标滚轮缩放图片”

小心Dom元素的name属性

对于一个用 JavaScript 获取到一个 DOM 节点的后,在说到属性的时候需要注意的是指 DOM 节点的属性还是 JavaScript 对象的属性(或说字段名)。一般来说,前者用 getAttribute/setAttribute 来访问/修改,后者用 object.field 来访问。然而,对于像 id、className 这些却属于 DOM 节点的 Attribute 范围。在说到 name 属性的时候,就更加复杂一点了,因为牵涉到 IE 的特殊处理。

当想用 setAttribute 给一个已有的(或动态创建的) DOM 元素设置 name 属性时,将会发现 IE6/7 跟 form 及相关表单元素合不来,根本就没有设置成功。

微软的文档,在 IE6/7 中,form 表单时的 name 属性是有些特殊的,用来标志提交的数据,跟平常的用途有些不一样。

When you submit a form, use the name property to bind the value of the control. The name is not the value displayed for the input type=button, input type=reset, and input type=submit input types. The internally stored value is submitted with the form, not the displayed value.

综合标准的做法,可以得到这样一个创建带 name 属性的 DOM 节点的代码: 继续阅读“小心Dom元素的name属性”