js 数组长度

当 js 数组 key 有一个为数值时,这个数组的长度将是最大 key + 1。如下:

<script type="text/javascript">
var a = []; 
a[10] = 1; 
a[109] = 2; 
console.log(a.length); // 110
a["abc"] = 1; 
console.log(a.length); // 110
</script>

当 js 数组 key 都为字符串时,这个数组的长度的长度为 0。如下:

<script type="text/javascript">
var a = []; 
a["abc"] = 1; 
console.log(a.length); // 0
</script>

如果不知道这个区别,那么我们在使用 for 循环时可能会遇到麻烦,如下:

<script type="text/javascript">
var a = []; 
a[10000000] = "abc";
var start = new Date().getTime(), len = a.length, j=0;
for(var i=0; i<a.length;i++){j++;}
var end = new Date().getTime();
console.log(end - start); // 146
</script>
<script type="text/javascript">
var a = []; 
a[10000000] = "abc";
var start = new Date().getTime(), len = a.length, j=0;
for(var i in a){j++;}
var end = new Date().getTime();
console.log(end - start); // 0
</script>

上面两段分别是检测对于同一个数组,使用 for 与 for in 的执行效率。使用 for 需要 146毫秒,而使用 for in 瞬间完成。这时就体现出 for in 的优势来了。 

还有一点就是对于数值 key 加不加引号都为理解为 数值。

为什么会有这样的疑惑,那就是因为PHP 不是这样的。如下:

<?php
 $a[100] = 123;
 $a["abc"] = 333;

 echo count($a); // 2

对于 Java等强类型语言就不会有这个问题,定义时必须指定长度~~。共勉之~

16
Mar 2015
AUTHOR WiFeng
CATEGORY Web
COMMENTS No Comments

简析Javascript变量作用域链

Javascript语言与服务端编程语言有一些不同,比如事件驱动、函数内定义新函数、函数即类、作用域链等等,这些特性促使这门语言相当奇葩。这一小节就来看看这个作用域链。

彻底搞明白作用域链原理,可以让你的程序少一些bug,也会节省一些开发调试时间。下面开始一段简单的代码:

<html>
<head></head>

<body>
<input id="test" type="text" />
</body>

<script>
function $(id) {
	return document.getElementById(id);
}

function fun1() {
	var a= 1;
	function inner() {
	    a++;
	    alert(a);
	}
	$("test").onclick = inner;
}
fun1(); 
</script>

</html>

这是一个非常容易读懂的事件绑定代码,先推测一下每次点击 input 会提示什么内容,然后拿这代码亲自执行一遍,看看你的推测对不对。如果是对,非常恭喜你,如果不对,那就接着往下看吧。

函数 inner 中的 a 没有使用 var 定义,所以执行时会使用当前函数外层的作用域,逐层向外查找,此时发现有定义 var a= 1,就停止查找,此时变量 a  的作用域就是fun1函数内部。此时变量 a 虽然在 函数 fun1 中,但是不会被垃圾回收机制回收掉,这是为什么,请关注 Javascript 变量生命周期。

相关概念:
函数运行在其定义的作用域,而不是执行的作用域。这个与作用域链是一个意思,只是表达方式不同。

24
Mar 2014
AUTHOR WiFeng
CATEGORY Web
COMMENTS No Comments

js之对象的属性

js 中是可以通过 new function 来达到创建对象的实现,好处自不用多说。来段代码演示一下:
<script>
function student(name, age, sex) {
	var name = name;
	this.age = age;
	sex = sex;
}

var jack = new student("jack", 14, "男");
alert(jack.name); // undefined
alert(jack.age);  // 14
alert(jack.sex);  // undefined
</script>

可以看到在 student 函数内部使用 this 引用赋值的变量是可以使用其对象调用的(如:age),反之却不能被其对象所调用。

为什么会说这个区别呢?这是因为大多数面向对象语言中,在此种这种情况下 this 是可以省去的。如果你已经习惯了 java 或者是 php,那么你写这种 js 时就要多留心了,小心被自己的惯性思维所欺骗。

11
Aug 2013
AUTHOR WiFeng
CATEGORY Web
COMMENTS No Comments

js之this的用法

this是Javascript语言的一个关键字。
它代表函数运行时,自动生成的一个内部对象,只能在函数内部使用。比如,

function test(){
this.x = 1;
}

随着函数使用场合的不同,this的值会发生变化。但是有一个总的原则,那就是this指的是,调用函数的那个对象。

下面分四种情况,详细讨论this的用法。

情况一 纯粹的函数调用

这是函数的最通常用法,属于全局性调用,因此this就代表全局对象Global。
请看下面这段代码,它的运行结果是1。

function test(){
this.x = 1;
alert(this.x);
}
test(); // 1

为了证明this就是全局对象,我对代码做一些改变:

var x = 1;
function test(){
alert(this.x);
}
test(); // 1

运行结果还是1。再变一下:

var x = 1;
function test(){
this.x = 0;
}
test();
alert(x); //0

情况二 作为对象方法的调用

函数还可以作为某个对象的方法调用,这时this就指这个上级对象。

function test(){
alert(this.x);
}
var o = {};
o.x = 1;
o.m = test;
o.m(); // 1

情况三 作为构造函数调用

所谓构造函数,就是通过这个函数生成一个新对象(object)。这时,this就指这个新对象。

function test(){
this.x = 1;
}
var o = new test();
alert(o.x); // 1

运行结果为1。为了表明这时this不是全局对象,我对代码做一些改变:

var x = 2;
function test(){
this.x = 1;
}
var o = new test();
alert(x); //2

运行结果为2,表明全局变量x的值根本没变。

情况四 apply调用

apply()是函数对象的一个方法,它的作用是改变函数的调用对象,它的第一个参数就表示改变后的调用这个函数的对象。因此,this指的就是这第一个参数。

var x = 0;
function test(){
alert(this.x);
}
var o={};
o.x = 1;
o.m = test;
o.m.apply(); //0

apply()的参数为空时,默认调用全局对象。因此,这时的运行结果为0,证明this指的是全局对象。
如果把最后一行代码修改为

o.m.apply(o); //1

运行结果就变成了1,证明了这时this代表的是对象o。


1
May 2013
AUTHOR WiFeng
CATEGORY Web
COMMENTS No Comments