读书笔记

Arguments对象


Arguments对象是一个集合,可以按照数字下标获取传递给函数的参数值.
例如:arguments.length可以获得传递过来的实参数量.

看书时发现对|arguments还是不太了解.于是搜索了一下相关.发现下面的这篇文章还比较通俗点:
http://www.xiaoxiaozi.com/2009/06/10/827/

在javascript函数体内,标识符arguments具有特殊含义。它是调用对象的一个特殊属性,用来引用Arguments对象。Arugments对象就像数组,注意这里只是像并不是。

javascript函数体内,arguments像数组(并不是真的数组,是一个Arguments对象,再次强调)一样,有length属性,可以代表传给函数的参数的个数.引用一个形式参数可以用参数名,也可以用arguments[]数组形式,其中arguments[0]表示第一个参数。
arguments.length属性:

js不会主动为你判断你到底给函数传了多少个参数,如果你多传了,多余的部分就没有被使用,如果你少传了,那么没传的参数值就是undefined,所以我们可以借助arguments的length属性来检测调用函数时是否使用了正确数目的实际参数,因为javascript是不会为你做这些事的



arguments还为我们提供了这样一种可能,就是为一个函数传任意数目的实际参数:
比如说,我想判断你传给我的一些数字的大小,取出最大的那个,对,没错,你传多少参数都行,但是前提是你要传数字,因为我在函数内部懒得判断了.
copycode:
function max()
{
//根据我上一篇日志,这已经是JavaScript内最小的数字了
var m = Number.NEGATIVE_INFINITY;
for(var i = 0; i < arguments.length; i++)
{
//只要有任何一个参数比m大,那么m就变成了这个参数的值
if(arguments[i] > m)
m = arguments[i];
}
return m;
}

说明一下arguments与真正传的形式参数是一致的:
比如,你给函数传了一个叫param的参数,并且只有这一个参数,那么param与arguments[0]都是对这个参数值的引用,改变其中一个值,即改变了二者所有的值.


简单的函数应用:
copycode:
<script type="text/javascript">
//用函数直接量,采用arguments.callee属性实现递归函数
document.write((function(x){if(x<=1) return 1;return x*arguments.callee(x-1);})(10));
</script>

小小子写的另一篇也不错:javascript 函数的方法call()和apply()

javascript面向对象(一)

今天看了好多关于javascript面向对象的知识.有一段是网上的载写的<精通javascript>的一部分.比较经典.
引用下.算是我今天的读书笔记吧!
学习的第一个方面:javascript的五个语言特性
第一:引用

JavaScript的一个重要的方面是引用的概念。引用就是指向对象实际位置的指针。这是一项极其强大的功能。前提是,实际的对象决不是一个引用:字符串总是一个字符串,数组总是一个数组。然而,多个变量可以引用相同的对象。JavaScript就是以这种引用引用机制为基础。通过维护一系列的指向其它对象的引用,语言为你提供了更大的弹性。

另外,对象能包括一系列的属性,这些属性简单地引用其它对象(如字符串,数字,数组等等)。当几个变量指向相同对象时,修改底层对象类型将会在所有的指点向它的变量上有所反映。例2-1即此一例,两个变量指向同一个对象,但是对对象内容的修改的反映是全局的。
程序2-1. 多变量引用单个对象的示例
//设置obj为一个空对象
var obj = new Object();

//objRef现在引用了别的对象
var objRef = obj;

//修改原始对象的属性
obj.oneProperty = true;

//我们可以发现该变化在两个变量中都可以看到
//(因为他们引用了同一个对象)
alert( obj.oneProperty === objRef.oneProperty );


我从前提到过自更改的对象在JavaScript里非常少见的。让我们看一个发生这一状况的实例。数组对象能够用push方法给它自己增加额外的项。因为在数组对象的核心,值是作为对象的属性存储的,结果类似程序2-1中的情形,一个对象成为全局被改动的(导致了多个变量的值被同时改变)。见程序2-2.

程序2-2. 自修改对象的例子

//创建一组项目的数组
var items = new Array( "one", "two", "three" );
//创建一个对项目数组的引用
var itemsRef = items;
//给原始数组添加一项
items.push( "four" );
//两个数组的长度应该相同,
//因为它们都指向相同的数组对象
alert( items.length == itemsRef.length );


记住这一点是很重要的:引用总是只指向最终被引用的对象,而不会是引用本身

第二:函数重载和类型检查

  在JavaScript的每一个函数里存在一个上下文相关的名为arguments的变量,它的行为类似于一个伪数组,包含了传给函数的所有参数。参数不是一真正的数组(意味着你不能修改它,或者调用push()方法增加新的项),但是你可以以数组的形式访问它,而且它也的确有一个length属性。程序2-5中有两个示例

程序2-5. JavaScript中函数重载的两个示例
copycode:
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 );
}
});

//一个使用任意数目参数创建一个数组的函数
function makeArray() {
//临时数组
var arr = [];
//遍历提交的每一个参数
for ( var i = 0; i < arguments.length; i++ ) {
arr.push( arguments[i] );
}
//返回结果数组
return arr;
}


第三:作用域

作用域是JavaScript中一个较难处理的特性。所有面向对象的编程语言都有某种形式的作用域;这要看是什么上下文约束着作用域。在 JavaScript里,作用域由函数约束,而不由块约束(如while,if,和for里的语句体)。最终可能使得一些代码的运行结果表面上显得怪异 (如果你来自一种块作用域语言的话)。程序2-10的例子说明了“函数作用域代码”的含义。

代码2-10. JavaScript中变量作用域是怎样工作的例子

copycode:
//设置一个等于"test"的全局变量foo
var foo = "test";
//在if块中
if ( true ) {
//设置foo为"new test"
//注意:这仍然是在全局作用域中
var foo = "new test";
}
//正如我们在此处可见,foo现在等于"new test"
alert( foo == "new test" );
//创建一个修改变量foo的函数
function test() {
var foo = "old test";
}

//调用时,foo却驻留在是在函数的作用域里面
test();

//确认一下,foo的值仍然是"new test"
alert( foo == "new test" );


在程序2-10中你会发现,变量位于在全局作用域。基于浏览器的JavaScript有趣的一面是,所有的全局变量实际上都是window对象的属性。尽管一些老版本的Opera浏览器或Safari浏览器不是这样,假定浏览器这样工作通常是一个很好的经验规则。程序2-11展示了一个这种例子

 程序2-11. JavaScript的全局变量与window对象的例子

//全局变量,包含字符串"test"
var test = "test";

//你会发现,我们的全局变量和window的test属性是相同的
alert( window.test == test );


最后,让我们来看看当一个变量漏定义时会怎样。程序2-12里,变量foo在test()的作用域里被赋值。但是,程序2-12里实际并没有(用var foo)定义变量的作用域。当变量foo没有明确定义时,它将成为全局变量,即使它只在函数的上下文使用。

程序2-12. 隐式全局变量声明的示例

//一个为变量foo赋值的函数
function test() {
foo = "test";
}
//调用函数为foo赋值
test();
//我们发现foo现在是全局变量了
alert( window.foo == "test" );


友情推荐参考:http://www.cnblogs.com/zhengchuyu/archive/2008/07/22/1248576.html

第四个:闭包

闭包意味着内层的函数可以引用存在于包绕它的函数的变量,即使外层的函数的执行已经终止。这一特殊的论题可能是非常强大又非常复杂的。我强烈推荐你们参考本节后面将提及的站点,因为它有一些关于闭包这一话题的精彩的信息。
我们先来看程序2-13所示的闭包的两个简单例子。 
   程序2-13. 闭包改善的代码清晰性的两例

copycode:
//得到id为"main"的元素
var obj = document.getElementById("main");

//改变它的边框样式
obj.style.border = "1px solid red";

//初始化一个1秒钟以后被调用的回调函数
setTimeout(function(){
//此函数将隐藏该元素
obj.style.display = 'none';
}, 1000);

//用来延迟显示消息的通用函数
function delayedAlert( msg, time ) {
//初始化一个被封套的函数
setTimeout(function(){
//此函数使用了来自封套它的函数的变量msg
alert( msg );
}, time );
}

//调用函数delayedAlert,带两个参数
delayedAlert( "Welcome!", 2000 );


第一个对setTimeout的函数调用,展示了一个的JavaScript新手遇到问题的通俗的例子。在JavaScript新手的程序里像这样的代码时常可以看到:

copycode:
setTimeout("otherFunction()", 1000);
//或者甚至
setTimeout("otherFunction(" + num + "," + num2 + ")", 1000);


使用闭包的概念,完全可能的把这种混乱的代码清理掉。第一个例子很简单;有一个回调函数在调用setTimeout函数以后1000微秒以后被调用,而它仍引用了变量obj(定义在全局范围,指向id为"main"的元素)。定义的第二个函数,delayedAlert,展示了一种解决出现的 setTimeout混乱的方案,以及函数作用域内可以有闭包的能力。

  你们应该可以发现,当在代码中使用这种简单的闭包时,你所写的东西的清晰性将会提高,免于陷入语法的迷雾之中。

copycode:
//id为"main"的一个元素
var obj = document.getElementById("main");

//用来绑定的items数组
var items = [ "click", "keypress" ];

//遍历items中的每一项
for ( var i = 0; i < items.length; i++ ) {
//用自执行的匿名函数来激发作用域
(function(){
//在些作用域内存储值
var item = items[i];
//为obj元素绑定函数
obj[ "on" + item ] = function() {
//item引用一个父级的变量,
//该变量在此for循环的上文中已被成功地scoped(?)
alert( "Thanks for your " + item );
};
})();
}


第五:上下文

在JavaScript中,你的代码将总是有着某种形式的上下文(代码在其内部工作的对象)。这也是其它面向对象语言所共有的功能,但它们都不如JavaScript处理得这样极端。
  
上下文是通过变量this工作。变量this总是引用代码当前所在的那个对象。记住全局对象实际上是window对象的属性。这意味着即使是在全局上下文里,this变量仍然引用一个对象。上下文可以成为一个强大的工具,是面向对象代码不可或缺的一环。

程序2-17展示了一些关于上下文的简单例子。

copycode:
var obj = {
yes: function(){
// this == obj
this.val = true;
},
no: function(){
this.val = false;
}
};
//我们看到,obj对象没有"val"的属性
alert( obj.val == null );
//我们运行yes函数,它将改变附着在obj对象的val属性
obj.yes();
alert( obj.val == true );
//然而,我们现在让window.no指向obj.no方法,并运行之
window.no = obj.no;
window.no();
//这导致obj对象保持不变(上下文则切换到了window对象)
alert( obj.val == true );
//而window的val属性被更新
alert( window.val == false );


你可能已经注意到,在程序2-17中,当我们切换obj.no方法的上下文到变量window时,笨重的代码需要切换函数的上下文。幸运的是,JavaScript提供了两种方法使这一过程变得更加易于理解和实现。程序2-18展示了恰能些目的的两种不同方法,call和apply。

程序2-18. 改变函数上下文的示例

copycode:
//一个简单的设置其上下文的颜色风格的函数
function changeColor( color ) {
this.style.color = color;
}

//在window对象上调用这个函数将会出错,因为window没有style对象
changeColor( "white" );

//得到一个id为"main"的对象
var main = document.getElementById("main");

//用call方法改变它的颜色为黑
//call方法将第一个参数设置为上下文,
//并其它所有参数传递给函数
changeColor.call( main, "black" );

//一个设置body元素的颜色的函数
function setBodyColor() {
//apply方法设置上下文为body元素
//第一个参数为设置的上下文,
//第二个参数是一个被作为参数传递给函数的数组
// of arguments that gets passed to the function
changeColor.apply( document.body, arguments );
}

//设置body元素的颜色为黑
setBodyColor( "black" );


http://www.blueidea.com/tech/web/2007/4618.asp

关联数组

关联数组是允许你通过字符串作为值的名字来找到某一个确定的值的数组.这些字符串叫做关键字.
点符号与方括号
在数组中

var str=[1,2,3];
str[1]

在对象中
var fun={
x:function(){
},
y:function(){
}}

fun.x();可以执行,fun['x']()也可以执行
具体可以看下面的实例


在CSS中的可以应用,例如下面
style.+得是它的一个属性.如果写成
style.stylename就错误了.应该它不是style的属性.
<select name="textAlign" id="select">
<option value="left">left</option>
<option value="right">right</option>
<option value="center">center</option>
</select>
<div id="box">thinkpad</div>
<script type="text/javascript">
function getValue(){
var styleName=this.name,
styleValue=this.value;
document.getElementById("box").style[styleName]=styleValue;
document.getElementById("box").innerHTML=styleValue;

}
document.getElementById("select").onchange=getValue;
</script>


还有其它应用,
如果在表单验证中.把常用的验证几项写成一个函数,在input上中个非w3c属性,通过dom查找这个非属性,来决定用那一个验证函数


这样的做法显然不能通过w3c验证.不过在实用中却很中用.

让IE也支持HTMLElement

今天看<精通JavaScritp>PDF电子书DOM的一章,其中讲了很多查找结点,操作结点的方法,刚开始是几个查找结点的方法,前一个结点,后一个结点,第一个子结点,最后一个子结点.父级结点;分别是

//前一个结点
function prev(elem){
do{
elem=elem.previousSibling;
}while(elem && elem.nodeType!=1);
return elem;
}
//后一个结点
function next(elem){
do{
elem=elem.nextSibling;
}while(elem && elem.nodeType!=1);
return elem;
}
//第一个子结点
function first(elem){
do{
elem=elem.firstChild;
}while(elem && elem.nodeType!=1);
return elem;
}
//父级元素结点
function parent(elem,num){
num=num || 1;
for(var i=0;i<num;i++){
if(elem!=null)
elem=elem.parentNode;
return elem;
}
}

例子


不过这样的代码并不优美.
在FF和Opera中存在一个强大的对象原型叫做HTMLElement,它允许你为每一个HTMLDOM元素绑定函数和数据.
<script type="text/javascript">
HTMLElement.prototype.next=function(){
var elem=this;
do{
elem=elem.nextSibling;
}while(elem && elem.nodeType!=1);
return elem;}
alert(document.getElementsByTagName('div')[0].next().nodeName);
</script>

不过IE并不支持它.所以自己得创造;
设置一个dom的方法
copycode:
var domMethod = {
//设置扩展dom的方法
extendDom: function(name,fn){

if(!document.all){ //除了ie而外的浏览器都能够访问到HTMLElement这个类
HTMLElement.prototype[name] = fn;
}else{
var _createElement = document.createElement;
document.createElement = function(tag){
var elem = _createElement(tag);
elem[name] = fn;
return elem;
}
var _getElementById = document.getElementById;
document.getElementById = function(id){
var elem = _getElementById(id);
elem[name] = fn;
return elem;
}
var _getElementsByTagName = document.getElementsByTagName;
document.getElementsByTagName = function(tag){
var arr = _getElementsByTagName(tag);
for(var i=0;i<arr.length;i++){
arr[i][name] = fn;
}
return arr;
}
}
}
}


例子说话

Object.prototype.toString





toString 方法是所有内建的 JScript 对象的成员。它的操作依赖于对象的类型:

Array 将 Array 的元素转换为字符串。结果字符串由逗号分隔,且连接起来。
Boolean 如果 Boolean 值是 true,则返回 “true”。否则,返回 “false”。
Date 返回日期的文字表示法。
Error 返回一个包含相关错误消息的字符串。
Function 返回如下格式的字符串,其中 functionname 是被调用 toString 方法函数的名称:
function functionname( ) { [native code] }
Number 返回数字的文字表示。
String 返回 String 对象的值。
默认 返回 “[object objectname]”,其中 objectname 是对象类型的名称。