Javascript语言特征

1、引用
引用指向的只能是具体的对象,而不是另一个引用(没有引用的引用的概念)。 在执行字符串链接操作时,结果总会是一个新的字符串对象,而非原字符串的修改版本(字符串链接时总是产生一个新字符串对象)。如下例子:

1
2
3
4
var item = "test";
var itemRef = item; //现在itemRef 和 item指向同一个字符串对象
item += "ing"; //现在新的字符串对象产生了,item指向了新字符串对象
alert( item != itemRef );

注意这个情况只是在字符串链接操作时。

2、函数重载和类型检查
函数重载必须依赖两件事情:判断传入参数数量的能力和判断传入参数类型的能力。
1) 判断传入参数数量
JavaScript的每个函数都带有一个仅在这个函数范围内作用的变量(contextual variable)称为参数(argument),它是一个包含所有传给函数的参数的伪数组(pseudo-array), 所以它并非真正意义的数组(也就是说你不能修改它,也不能用push()来添加新元素),但可以访问其中的元素,也有.length属性[只读]。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function sendMessage( msg, obj ) {
if( arguments.length == 2){
obj.handleMsg( msg );
}else{
alert( msg);
}
}
// 仅用一个参数调用
sendMessage("Hello World!");
// 使用两个参数调用
sendMessage("How are you?", {
handleMsg: function( msg ){
alert("This is a custom message:" + msg);
}
});

还有一个用来判断传入参数类型的方法。如果没有提供参数,它的类型比为undefined,可以利用这特征来作判断。

1
2
3
4
5
6
function displayerror( msg ) {
if( typeof msg == 'undefined' ) {
msg = "An error occurred.";
}
alert( msg );
}

2) 判断传入参数类型
JavaScript的类型检查有两种特别有用的方法:
第一种方法是使用typeof操作符。这个工具提供了一个字符串名称,用于表达变量内容的类型。当变量不是object或array类型时,这是最完美的解决方法了。但是对于自定义的对象就不能用这个方法进行类型检查,因为它只返回object,很难跟其他的object区分开来。

第二种检查对象类型的方法,需要引用所有JavaScript对象都带有的一个属性,称为构造函数(construstor)。这个属性引用的是原本用来构造该对象的那个函数

变量类型检查对照表

1
2
3
4
5
6
7
8
变量			typeof变量		变量.构造函数
{an:"object"} object Object
["an","array"] object Array
function(){} function Function
"a string" string String
66 number Number
true boolean Boolean
new User() object User

可以使用{}构建一个对象,使用[]构建一个数组,construstor保存的就是这个对象的构造函数名,构造函数 作为 对象类型 引用(按照严格面向对象的说法就是构造函数指明了构造这个对象的类,它引用到了类,所以它是一个对象),注意typeof始终返回一个字符串作为类型标识。
3、作用域
在Javascript里,作用域是由函数划分的,而不是由块(block)划分的。基于浏览器的Javascript的一个有趣特征是,所有属于全局作用域的变量其实都是window对象的属性。如果变量没有显式定义,它就是全局定义的,虽然它可能只在这个函数作用域的范围内使用。

4、闭包
闭包(closure)意味着内层的函数可以引用存在于包围它的函数内的变量,即使外层函数的执行已经终止。

闭包能实现的额外作用:
1) 在一些函数式程序设计语言里,有一种称为Curry化的技术。本质上,Curry化是一种通过把多个参数填充到函数体中,实现将函数转换为一个新的经过简化的(使之接受参数更少)函数的技术。

1
2
3
4
5
6
7
8
9
10
function addGenerator(num)
{
//返回一个函数
return function(toAdd)
{
return num+toAdd;
};
}
var addFive=addGenerator(5);
aler(addFive(4)==9);

2) 通过自执行的匿名函数你可以把所有原本属于全局的变量都隐藏起来。

1
2
3
4
5
6
7
8
9
10
11
12

(
function()
{
//这个变量如果没有用自执行的匿名函数包围起来那么它就是全局的
var msg="Thanks for visiting!";
window.onunload=funtion()
{
alert(msg);
};
}
)();

这是一种有效的避免变量冲突的方法。

3) 使用匿名函数来激发出创建多个使用闭包的函数所需的作用域

1
2
3
4
5
6
7
8
9
10
var obj=document.getElementById("main");
var items=["click","keypress"];
for(var i=0;i < args.length; i++ ) {
(function(){
var itemm = item[i];
obj["on" + item ] = function() {
alert( "Thanks for your " + item );
}
})();
}

关于闭包的工作原理,可以参考:http://jibbering.com/faq/notes/closures/

5、上下文对象
在Javascript中,代码总是有一个上下文对象(代码处在该对象内)。上下文对象是通过this变量体现的,这个变量永远指向当前代码所处的对象中。全局对象其实是window对象的属性。这意味着即使是在全局上下文中,this变量也能指向一个对象。Javascript提供了call和apply两个方法,可以使用这两个方法改变上下文对象。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function changeColor( color ) {
this.style.color = color;
}
// 在window对象中待用函数会失败,因为它没有style属性
changeColor("while");
//找出ID为main的节点
var main = document.getElementById("main");
//使用call方法将它的颜色设置为黑色。call方法将上下文对象设置为第一个参数,并将其它产生作为原函数的参数
changeColor.call(main, "black");
//设置body元素颜色的函数
function setBodyColor() {
// apply方法将上下文对象设置为第一个参数指定的body元素,第二个元素是传给函数的所有参数的数组
changeColor.apply(document.body, arguments);
}
// 将body的背景色设置为黑色
setBodyColor("black");

这些精彩内容总结来自Pro Javascript Techniques一书,此书作者为jQuery之父John Resig。

坚持原创技术分享,您的支持将鼓励我继续创作!