<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>無標題文檔</title> <script type="text/javascript"> var array=[1,2,3,4,5,6]; var arr=array.map(function(item){ return item*2; }); alert(arr[0]);// 2 ------------------------------------------------ /////變量的做用域 var variable="out"; function func() { variable="in"; alert(variable); } func(); // 打印"in" alert(variable); // 打印"in" ------------------------------------------------ var object={ field:"self", printInfo:function(){ alert(this.field); } } alert(object.field); //"self" object.printInfo(); // "self" for(var key in object){ alert(key+" : "+object[key]); } ------------------------------------------------ ///JavaScript對象 function Base(name) { this.name = name; this.getName = function () { return this.name; } } function Child(id) { this.id = id; this.getId = function () { return this.id; } } //將Child原型指向一個新的base對象 Child.prototype = new Base("base"); //實例化一個Child對象 var c1 = new Child("child"); //調用c1自己的getId方法 alert(c1.getId()); //child //因爲c1從原型鏈上「繼承」到了getName方法,所以能夠訪問 alert(c1.getName()); //base //////註解:因爲遍歷原型鏈時是由下而上的,因此最早遇到的屬性值最早返回 function Person(name, age) { this.name = name; this.age = age; this.getName = function () { return this.name; } this.getAge = function () { return this.age; } } var tom = new Person("Tom", 30); var jerry = new Person("jerry", 40); ////註解:經過原型鏈,能夠實現繼承/重載等面向對象的js代碼。固然這個機制並不是基於類,而是基於原型 ------------------------------------------------ //定義個「類」,Address function Address(street, xno) { this.street = street || "黃泉路"; this.xno = xno || 135; this.toString = function () { return "street:" + this.street + ",No:" + this.xno; } } //定義另一個「類」,Person function Person(name,age,addr){ this.name = name || "未知"; this.age = age; this.addr = addr || new Address(null, null); this.getName = function () { return this.name; }; this.getAge = function () { return this.age; }; this.getAddr = function () { return this.addr.toString(); }; } //經過new 操做符來建立兩個對象,注意,這個兩個對象是相互獨立的實體 var jack = new Person("jack", 26, new Address("青海路", 123)); var abruzzi = new Person("abruzzi", 26); //查看結果 alert(jack.getName()); //jack alert(jack.getAge()); //26 alert(jack.getAddr()); //street:青海路,No:123 alert(abruzzi.getName()); //abruzzi alert(abruzzi.getAge()); //26 alert(abruzzi.getAddr()); //street:黃泉路,No:135 ------------------------------------------------ ////函數做用域 var str = "global"; function scopeTest() { alert(str); var str = "local"; alert(str); } scopeTest(); //運行結果 undefined local ///註解:由於在函數scopeTest的定義中,預先訪問了未聲明的變量str,而後纔對str變量進行初始化,因此第一個alert會返回undefined錯誤。 ///那爲何函數這個時候不會去訪問外部的str變量呢? ///這是由於在詞法分析結束後,構造做用域的時候會將函數內定義的var變量放入該鏈,所以str在整個函數內部是可見的(從函數體的第一行到最後一行), ///因爲str變量自己是未定義的,程序順序執行,到第一行就會返回爲定義,第二行爲str賦值 ------------------------------------------------ /////閉包 ///因爲在javaScript中,函數是對象,對象是屬性集合,而屬性的值有能夠是對象,則在函數內定義函數成爲理所固然,若是在函數func內部聲明函數inner,而後在函數外調用inner,這個過程即產生閉包。 var outter = []; function clouseTest() { var array = ["one", "two", "three", "four"]; for (var i = 0; i < array.length; i++) { var x = {}; x.no = i; x.text = array[i]; x.invoke = function () { alert(i); } outter.push(x); } } //調用 clouseTest(); outter[0].invoke(); outter[1].invoke(); outter[2].invoke(); outter[3].invoke(); ///運行結果是 4 4 4 4 爲何不是0 1 2 3呢? //由於每次在迭代的時候,語句x.invoke=function(){alert(i);}並無被執行,只是構建了一個函數體爲「alert(i);」的函數對象而已。 //若是每次迭代的時候語句x.invoke=function(){alert(i);}執行的話,則調用clouseTest()的時候則就會彈出對話框了,事實上卻沒有彈,證實沒有執行 //如何解決呢? var outter = []; function clouseTest2() { var array = ["one", "two", "three", "four"]; for (var i = 0; i < array.length; i++) { var x = {}; x.no = i; x.text = array[i]; x.invoke = function (no) { alert(no); }(i);//調用 outter.push(x); } } //調用 clouseTest2(); ------------------------------------------------ ///封裝 var person = function () { //變量的做用域爲函數內部,外部沒法訪問 var name = "張飛"; return { getName: function () { return name; }, setName: function (newName) { name = newName; } } }(); alert(person.name);//直接訪問,結果爲undefined alert(person.getName()); //張飛 person.setName("關羽"); alert(person.getName()); //關羽 function Person() { var name = "張飛"; return { getName: function () { return name; }, setName: function (newName) { name = newName; } } }; var john = new Person(); alert(john.getName()); //張飛 john.setName("john"); alert(john.getName()); // john ////在不一樣的Javascript解釋器實現中,因爲解釋器自己的缺陷,使用閉包可能形成內存泄露(嚴重影響用戶體驗) ///如:對象A引用B,B引用C,而C又引用A ------------------------------------------------ ///【面向對象的JavaScript】 //原型繼承:js中的繼承能夠經過原型鏈來實現,調用對象上的一個方法,因爲方法在javascript對象中是對另外一個函數對象的引用,所以解釋器會在對象中查找該屬性, //若是沒有找到,則在其內部對象prototype對象上搜索。因爲prototype對象與對象自己的結構是同樣的,所以這個過程會一直回溯到發現該屬性,不然,報錯 function Base() { this.baseFunc = function () { alert("基礎行爲");} } function Middle() { this.middleFunc = function () { alert("中間行爲");} } Middle.prototype = new Base(); function Final() { this.finalFunc = function () { alert("最終行爲");} } Final.prototype = new Middle(); function Test() { var obj = new Final(); obj.baseFunc(); obj.middleFunc(); obj.finalFunc(); } Test();///// 基礎行爲 中間行爲 最終行爲 // 原型鏈示意圖 見圖 P76 ///new 操做符 function Shape(type) { this.type = type || "rect"; this.calc = function () { return "calc," + this.type;} } var triangle = new Shape("triangle"); alert(triangle.calc()); var circle = new Shape("circle"); alert(circle.calc()); ////註解:Javascript和其餘面向對象的new操做符不同,triangle,circle可能在Java中是Shape對應的具體對象,可是在js中並不是如此(new比較特殊) ////首先,建立一個空對象,而後用函數apply方法,將這個空對象傳入做爲apply的第一個參數以及上下文參數,這樣的函數內部的this將會被這個空的對象所替代。 var triangle = new Shape("triangle"); ///至關於下面的代碼 var triangle = {}; Shape.apply(triangle, ["triangle"]); ------------------------------------------------ ///柯里化 //柯里化就是餘下將函數的某些參數傳入,獲得一個簡單的函數,可是預先傳入的參數被保存在閉包中,所以會有一些奇特的特性 var addr = function (num) { return function (y) { return num + y;} } var inc = addr(1); var dec = addr(-1); alert(inc(99)); //100 alert(dec(101)); // 100 alert(addr(100)(2)); // 102 alert(addr(2)(100)); // 102 ------------------------------------------------ //開發智力(坑爹) //函數的不動點 function fixedPoint(Func, first) { var tolerance = 0.00001; function closeEnough(x, y) { return Math.abs(x - y) < tolerance; }; function Try(guess) { var next = Func(guess); //alert(next+" "+ guess); if (closeEnough(guess, next)) { return next;//返回小的 } else { return Try(first);//遞歸調用 } }; return Try(first); } //數層嵌套函數 function sqrt(x) { var Func = function (y) { var div = function (a, b) { return (a + b) / 2; } return div(y, x / y); } return fixedPoint(Func, 1.0); } alert(sqrt(100)); ------------------------------------------------///原型鏈:因爲原型對象自己也是對象,它也有本身的原型,而他本身的原型對象又能夠有本身的原型,這樣就組成了一條鏈,這個鏈就是原型鏈 ///Javascript引擎在訪問對象的屬性時,若是在對象自己中沒有找到,則會去原型鏈中查找,若是找到,直接返回值,若是整個鏈都遍歷且沒有找到屬性,則返回undefined。原型鏈通常是實現爲一個鏈表,這樣就能夠按照必定的順序來查找 var base = { name: "base", getInfo: function () { return this.name; } } var ext1 = { id: 0, __proto__:base } var ext2 = { id: 9, __proto__:base } alert(ext1.id); //0 alert(ext1.getInfo()); //base alert(ext2.id); //9 alert(ext2.getInfo()); // base //原型鏈圖 見P105 var base = { ///(原型對象) name: "base", getInfo: function () { return this.id + " : " + this.name;} }; var ext1 = { ///(原始對象) id: 0, __proto__:base }; alert(ext1.getInfo()); // 0 : base ///註解:getInfo函數中的this表示原始的對象,並不是原型對象,上例中的id屬性來自於ext1對象,而name來自base對象 ///若是沒有顯示的聲明本身的」__proto__「屬性,這個值默認的設置爲Object.prototype,而Object.prototype的「__proto__」屬性值爲「null」,標誌着原型鏈的終結 ------------------------------------------------ ///執行期上下文:按照ECMAScript的規範,一共有三種類型的代碼,全局代碼、函數代碼、以及eval代碼 ///this上下文:ECMAScript的規範中對this的定義爲:this是一個特殊的對象,與執行期上下文相關,所以能夠稱爲上下文對象。 ///this是執行期上下文對象的一個屬性(執行期上下文對象包括變量對象、做用域鏈以及this)。執行期上下文對象有三類,當進入不一樣的上下文時,this的值會肯定下來,而且this的值不能更改。 ///在執行全局代碼時,控制流會進入全局執行期上下文,而在執行函數時,又會有函數執行期上下文 var global = this; var tom = { name: "Tom", home: "desine", getInfo: function () { alert(this.name + ", from " + this.home); } }; tom.getInfo(); // Tom,from desine var jerry = { name: "Jerry", getInfo:tom.getInfo }; jerry.getInfo(); // Jerry,from undefined global.getInfo = tom.getInfo; global.getInfo(); // ,from undefined </script> </head> <body> </body> </html>