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属性”

于悄无声息中获取你的访问记录

当访问某个网站时,不经意中,就被别人猜测到你是否访问过某个网站,而这却没有什么技术性的东西,也不算是违法的行为。

奥秘在于浏览器对于访问过的链接会用伪类 :visited 来标识。

那么很容易想到的一个方法就是,用 a:visited 来设定一个特定的颜色值,比如 red。然后从一个 URL 列表中来动态创建一个链接,然后获取其颜色(各浏览器返回的结果不完全一致,可能是 rgb 值,也可能是 hex 值),如果跟设定的颜色一致,那么就可以确定用户在当前浏览器访问过该链接。

实际测试中会发现,新版本的浏览器(如Chrome 14, IE9, FF5)对于 a:visited 的样式是成功应用的,但获取到的颜色却不是对应的设定,而是 a:link、a 甚至是默认的颜色,从而无法判断用户是否访问过该链接。这是现代浏览器在这方面的安全保护,一方面使样式可以正常生效,另一方面却防止了 JS 窃听。然而,在一些旧版本的浏览器(比如IE6~8, FF3)上面却没有这个保护措施,因而可以判断出是否在该浏览器上访问过该链接。

对于以上依赖于 JavaScript 的窃听,很容易想到的一个防止方法就是禁止 JavaScript 的运行。没错,抛开种种不便来说,的确可以达到防止以上窃听的目的,即便是 IE6 等老一代浏览器。但是,却防止不了 CSS 的窃听方式。

又是如何利用 CSS 来进行判断窃听的吗? 继续阅读“于悄无声息中获取你的访问记录”