<script language="javascript">
//切記特殊的兩種函式宣告方式
/*
//Function 構造
var f=new Function("x","document.write(x);");
f(2);
//函數直接量
var g=function(y)
{
alert("I am the Function g().");
}
g();
*/
function Rectangle_area(){return this.width*this.height;}
function Rectangle_perimeter(){return 2*(this.width+this.height);}
function Rectangle_set_size(w,h){this.width=w;this.heigh=h;}
function Rectangle_enlarge(){this.width*=2;this.height*=2;}
function Rectangle_shrink(){this.width/=2;this.height/=2;}
//初學javascript中的物件導向的編程方式
//構造Retangle對象定義一個建構函式方法
//建構函式不僅要初始化屬性,還給方法賦值
function Rectangle(w,h)
{
//初始化對象的屬性
this.width=w;
this.height=h;
//定義對象的方法
this.area=Rectangle_area;
this.perimeter=Rectangle_perimeter;
this.set_size=Rectangle_set_size;
this.enlarge=Rectangle_enlarge;
this.shrink=Rectangle_shrink;
}
var r=new Rectangle(3,4);
var a=r.area();
r.enlarge();
var p=r.perimeter();
document.write("The rectangle's width is :"+r.width+"<br />This rectangle'height is :"+r.height);
//alert("The rectangle's area is :"+a+",The rectangle'perimeter is :"+p);
/*
自訂異常錯誤!
throw new Error("there is something wrong!");
*/
/*
直接函數的更多應用
直接函數和Function建構函式一樣,函數直接兩建立的是未命名函數,而且不會自動地將這個函數儲存在
屬性中。但是,比起Function函數構造建立的函數主體必須用一個字串說明,用這種方式來表達一個長
而複雜的函數是很笨拙的。但是函數直接量的主體使用的卻是標準的javascript文法。而且函數直接量植被
解析和編譯一次,而作為字串傳遞給Function建構函式的javascript代碼則在每次調用建構函式時只需
被解析和編譯一次。
*/
//作為資料的函數執行個體
function add(x,y){return x+y;}
function subtract(x,y){return x-y;}
function multiply(x,y){return x*y;}
function divide(x,y){return x/y;}
//以下的函數可以將上面的某個函數作為參數
//他的兩個參數是兩個運算數。
function operate(operator,operand1,operand2)
{
return operator(operand1,operand2);
}
//我們可以調用該函數
var i=operate(add,2,3);
document.write("<br />operate(add,2,3)的結果是:"+i);
//看到這裡我不禁想到了c#中的委託代理
//這裡就給了我們一個生動形象的執行個體來協助我們理解委託代理
//C#中的委託代理的目的不就是為了將函數作為參數來傳遞
//在javascript中作為資料的函數,說白了就是為了實現我們在c#中的委託代理的目標.
var operators=new Object();
operators["add"]=function(x,y){return x+y;}
operators["subtract"]=function(x,y){return x-y;}
operators["multiply"]=function(x,y){return x*y;}
operators["devide"]=function(x,y){return x/y;}
operators["pow"]=Math.pow;
//以下的函數將運算子名作為參數,在數組中檢索這個運算子.
//然後對運算數調用檢索到的函數
//注意調用這個運算子函數的文法
function operate2(op_name,operand1,operand2)
{
if (op_name==null)
{
return "unknown operator!";
}
else
{
return operators[op_name](operand1,operand2);
}
}
//我們就可以使用以下的方式調用該Function Compute值 ("hello"+" "+"world!")
//var j=opertate2("add","Hello",operate2("add"," ","world!"));
var k=operate2("add","Hello",operate2("add"," ","world!"));
document.write("<br >opertate2('add','Hello',operate2('add','','world!'))的結果是:"+k);
document.write("<br>operate2('pow'.10,2)的結果是:"+operate2("pow",10,2));
//個人意見
//這種使用方法實際上就是在javascript中提到的屬性的關聯陣列的用法,為我們的編程提供了
//強大的靈活性.
//javascript函數的主體是在局部範圍中執行的,該範圍不同於全域範圍.這個新的範圍
//是通過調用對象添加到函數範圍鏈的頭部建立的.因為調用對象是範圍鏈的一部分,所以
//在函數體內可以把這個調用對象的德屬性作為變數來訪問.用var語句聲明的局部變數建立後
//作為調用對象的屬性,而且函數的形式參數也可用於調用對象的屬性.
/*
函數調用的實際參數:Arguments對象.
*/
function f(x,y,z)
{
//首先檢查傳遞參數的數量是否正確.
if (arguments.length!=3)
{
throw new Error("Function f called with "+arguments.length+"arguments ,but it expects 3 arguments!");
}
}
//f(1,2,6,6);
function max()
{
var m=Number.NEGATIVE_INFINITY;
//遍曆所有參數,檢索並儲存其中最大的參數
for (var i=0;i<arguments.length ;i++ )
{
if(arguments[i]>m) m=arguments[i];
document.write("<br />arguments["+i+"]="+arguments[i]);
}
return m;
}
var largest=max(1,6,9,100,99,5);
document.write("<br />max(1,6,9,100,99,5)的結果是:"+largest);
/*
以上的執行個體中的Arguments對象很容易讓我們認為它是一個數組,
但我要說明的一點就是這裡的arguments不是一個數組而是一個對象,雖然它也有length屬性
但我們如果把它看作偶然具有了一些帶編碼的屬性的對象更合適些.
*/
//aruments對象還有callee屬性
//用來引用當前正在執行的函數.看下面這個求階乘的函數
var t=function(x)
{
if(x<=1) return 1;
return x*arguments.callee(x-1);
}
document.write("<br />5的階乘是:"+t(5));
//函數的屬性和方法
//知道了arguments數組的length屬性指定了楚地為該函數的實際參數數目.但是函數自身的length屬性的含義
//卻非如此,它是唯讀.返回的是函數需要的實際參數數目,也就是在函數的形式參數列表中聲明的形式參數
//的數目.
function check(args)
{
var actual=args.length;
var expected=args.callee.length;
if (actual!=expected)
{
throw new Error("Wrong number of arguments:expected : "+expected +";actually passed "+actual);
}
}
function f2(x,y,z)
{
check(arguments);
return f2.counter++;
}
//f2(4);
//同時函數還可以定義自己的屬性
f2.counter=0
document.write("<br />第一次引用f2時的counter屬性:"+f2(1,1,1)); //此時counter=2
document.write("<br />第二次引用f2時的counter屬性:"+f2(1,1,1)); //此時counter=3
//document.write("<br />第三次引用f2時的counter屬性:"+f2.counter); //此時counter=3
//函數的apply()和call()方法
//call 和apply方法的第一個參數都是要調用的函數對象,在函數體內這一參數可以使用this的值,
//call()的剩餘參數是傳遞給要調用的函數的值.
//apply()區別於call()的地方就是apply()的參數是用數組來傳遞的
var d=new Array(1,2,3);
f2.call(f,1,2,3); //此時counter=4
document.write("<br />第三次引用f2時的counter屬性:"+--f2.counter);
f2.apply(this,d); //此時counter=2
document.write("<br />第四次引用f2時的counter屬性:"+f2.counter);
f.call(f2,1,2,3); //此時counter=2,這裡沒有調用f2
document.write("<br />第五次引用f2時的counter屬性:"+f2.counter);
//以上現象比較怪異,應該多想想!
//實際上以上主要在讓我熟悉++的運算
</script>