《JavaScript高級程序設計(第3版)》教程大綱

詞條javascript

《JavaScript高級程序設計》是2006年人民郵電出版社出版的圖書,做者是(美)(Nicholas C.Zakas)扎卡斯。本書適合有必定編程經驗的開發人員閱讀,也可做爲高校相關專業課程的教材。java

獻給搬磚人士,求職人士很不錯的基礎紮實筆記算法


前四章

js誕生於1995年當時它的主要目的是處理驗證操做現在發展成爲一門強大的編程語言,由三部分組成:核心(ECMAScript)DOM文檔對象模型、 BOM瀏覽器對象模型編程

js 放置在 頁面的合理位置 對於優化加載有很大的幫助

切記平穩退化,若是不支持的狀況下 有不少種方案 ,書中提到了數組

<noscript>  元素  </noscript>

當頁面支持腳本,用戶永遠也看不到它,儘管他是頁面的一部分。瀏覽器

語句結尾加上分號,在某些狀況下會增進代碼的性能,由於解析器沒必要花時間推測應該在哪裏插入分號了。

1、數據類型 性能優化

關於 undefined類型,在使用var聲明變量但未對其加以初始化這個變量的值就是undefined,包含undefined值的變量與還沒有定義的變量還不同。閉包

var message;

alert(message) // undefined
alert(age) // 產生錯誤

關於 NANapp

即非數值,不是一個數字。框架

NAN與任何值都不相等,包括它本身
alert(isNAN(NAN))  //是否 不是一個數字  true
alert(isNAN(10)) // false
alert(isNAN('ni')) // true
alert(isNAN(true)) // false 由於true 能夠被轉換爲1
typeof() 用來檢測給定變量的數據類型
1.undefined  聲明變量沒有定義
2. null 空對象指針 
3. bloolean 
4. number  數值轉換 Number()函數在轉換字符串時比較複雜並且不夠合理,推薦使用,parseInt()parseFloat()
5. string 字符串類型  toString() 有個缺點 對null 和 undefined 不起做用
6. string() 方法更全面
7. object 對象

2、語句

do-whlie語句 是一種後測試循環語句,換句話說代碼至少執行一次

do{
    i+=2;
}whlie(i<10)

whlie語句屬於前測試循環語句,相對for語句也是

var i = 0
whlie(i<10){
    i+=2
}

關於break和continue語句

var num = 0;
for(var i = 0;i++;i<num.length){
    if(i%5==0){
        break;
    }
    num++;
}

alert(num) //4  break 是當即退出循環強制執行循環後面的語句


var num = 0;
for(var i = 0;i++;i<num.length){
    if(i%5==0){
        continue;
    }
    num++;
}

alert(num) //8  continue 退出循環後從循環頂部繼續執行
  1. for in 語句 用來枚舉對象屬性 注意一點 : 輸出的屬性名 順序不可預測。
  2. 理解參數 : 經過 arguments 對象的length 能夠獲知有多少個參數 傳遞給了函數。

函數體內能夠經過arguments 對象來訪問這個參數數組 類數組
經過arguments[0]訪問第一個參數,arguments[1]訪問第二個參數
函數沒有重載,定義兩個相同名字的函數,後一個會覆蓋前一個 經過檢查傳入函數中參數的類型和數量作出不一樣的反應,來模擬方法重載,以下所示。

function add(){
    if(arguments.length ==1){
        alert(arguments[0]+10)
    }else if(arguments.length ==2){
        alert(arguments[0]+arguments[1])
    }
}

add(10) //20
add(10,20) //30

js 變量包含兩種數據類型 其一 基本數據類型 其二 引用數據類型


3、基本數據類型與引用類型

基本數據類型指的是簡單的數據段,引用類型保存在內存對象中不能直接操做對象的內存空間,操做對象是實際上操做的是對象的引用。

var num1 = 5
var num2 = num1

num2與num1是徹底的獨立的,兩個變量互不影響,是副本的關係
var obj = new object ;
var obj2 = obj;

obj.name = 'nihao';
alert obj2.name    結果是 nihao

不一樣的是 這個值的副本實際是 指向了同一個對象 當obj 添加了name屬性後 能夠經過 obj2 來訪問

函數的參數 實際上是其函數的局部變量

每一個函數都有本身的執行環境,當代執行的時候會建立一個做用域鏈,對環境的全部變量作有序的訪問

查詢標示符 也就是 搜索 過程 若是局部環境找到了該標識符 則搜索過程中止 不然 一直追溯到全局環境的變量

做用域鏈 引起了閉包的概念 全局變量只能訪問全局的環境 而局部環境不只能夠訪問本身 還能夠訪問其 父級

js 是一門具備垃圾 收集機制的編程語言 沒必要關心內存問題 標記清除是目前主流的 垃圾收集算法給當前不使用的值加上標記而後再回收其內存 引用計數 目前再也不使用的算法,解除引用對垃圾回收機制有好處是很好的性能優化方案


第五章 引用類型

  1. 如何使用對象
  2. 建立並操做數組
  3. 理解js的基本數據類型

引用類型,有時候也稱爲對象定義由於他們描述的是一類對象所具備的屬性和方法。

1、object類型

建立object實例的方法:

  1. new操做符後面加上object構造函數
  2. 字面量表示法
var per = {
    name: '',
    age: 23
}

思考題---基於typeof 檢測屬性是否存在,使用字面量來指定不一樣的數據,作不一樣的顯示

function show(arg){
    var output = '';
    if(typeof arg.name === 'string'){
        output += 'nihao' + arg.name;
    }
    if(typeof arg.age === 'number'){
        output+= 'Age:'+ arg.age
    }
    alert(output);
}
show({
    name:'lish',
    age: 23
})

show({
    name:'zbg'
})

2、array類型

與其餘語言的區別: 都同爲數據的有序列表,可是js的數組每項能夠保存任何類型的數據

建立方式 同object類型

數組的length屬性 不是隻讀的,能夠修改!

數組檢測 有兩個問題:instanceof、array.isArray(),若是有多個框架會有多個全局執行環境會存在不一樣版本的構造函數,後者目的是肯定這個值是否是數組,不管是在那個環境建立的

轉換方法: 全部對象都具備toLocaleString、toString、valueOf ,前者與後二者不一樣的是爲了取每一項的值調用的是每一項的toLocaleString,而不是toString。
最後使用join()重現了toString的方法,傳遞逗號將以逗號分割,傳遞雙豎線將以雙豎線分割

ecmascript專門爲數組提供了push和pop方法,模擬棧方法,後進先出。
unshift和shift先進先出。

重排序方法:sort()

function com (val1,val2){
    if(val1<val2){
        return -1;
    }else if(val2>val2){
        return 1;
    }else{
        return 0
    }
}
var arr = [12,2,3,34,567];
arr.sort(com)
alert (arr);

操做方法: concat() 不改變原數組,複製原數組返回副本,會被添加到原數組的末尾

var arr1 = [1,23,3];
var arr2 = arr1.concat("one",[8,"two"])
arr2 => 1,23,3,one,8,two

slice()用於截取數組,不改變原數組建立一個新數組

arr.slice(1) 從下標1開始到結束
arr.slice(1,4)同理
若是是負數,用數組的長度作運算,再若是結束位置小於起始位置返回空數組

splice() 用於刪除、插入、替換數組

arr.splice(0,1) 從第零個開始刪除1位
arr.splice(1,0,"one") 從第一個位置開始不刪除 插入一項
arr.splice(1,1,"two") 從第一個位置刪除一位 插入一項

filter() 用於數組篩選

var bg = arr.filter(function(item,index,array){
    return (item>2)
})
console.log(bg)

map()方法 和foreach() 相似

var bg = arr.map(function(item,index,array){
    return (item+2)
})
console.log(bg)

歸併方法 reduce()和reduceRight()

使用歸併方法求數組之和

var val = [1,2,3,4,5]
var sum = val.reduce(function(pre,cur,index,array){
    return pre+cur
})
alert(sum) 15

pre表明前一項 cur表明當前項  
reduce 和 reduceRight 結果相同但取決於從哪頭開始遍歷數組。

3、date類型

經常使用的時間戳

`var start = +new Date()
dosomething();
var end = +new Date()
result = end-start`

4、regExp類型

匹配第一個 bat 或者 cat 不區分大小寫

var pattern = /[bc]at/i;

匹配第一個[bc]at 不區分大小寫

var pattren = /\[bc]\at/i;

匹配全部以 at結尾的字符不區分大小寫

var partten = /.at/gi;

匹配全部以 .at 結尾的字符不區分大小寫

var partten = /\.at\/gi;

test()方法

var text = "000-00-0000";
var partten = /\d{3}-\d{2}-\d{4}/;
if(partten.test(text)){
    alert('yes')
}

5、function類型

函數沒有重載

var add  = function(){
    return num+100
}
add  = function(){
    return num+100
}
var result = add(200)  //300

在建立第二個函數時,實際上覆蓋了第一個函數的變量

函數聲明與函數表達式 聲明提早

函數聲明由於在代碼執行以前,引擎會聲明函數並將他們放到源代碼樹的頂部,
而對於表達式:

alert(sum(10,10));
var sum = function(){
    return num+num2
}

在執行到語句以前,變量sum中不會保存對函數的引用

做爲值的函數

假想根據某個對象屬性對數組進行排序

function newsort(pro){
    return function(obj1,obj2){
        var val1 = obj1[pro];
        var val2 = obj2[pro];
        if(val1<val2){
            return -1;
        }else if(val1>val2){
            return 1
        }else{
            return 0
        }
    }
}

var data = [{name:'lj', age:23},{name:'db', age:45}];
data.sort(newsort(name)) //按姓名排
data.sort(newsort(age)) //按年齡排

函數內部屬性

函數內部有兩個特殊的對象:arguments this,arguments主要保存函數的參數它還有一個屬性callee 是個指針 指向擁有arguments對象的函數

例如很是經典的階乘函數

function fact(num){
    if(num<=1){
        return 1
    }
    else{
        return num* fact(num-1)
    }
}

爲了消除函數執行與函數名的耦合現象可使用arguments.callee(num-1)
替代 fact(num-1)

在解除了耦合狀態以後 newfact能夠正常計算,但fact 只能返回0
var newfact = fact;
fact = fuction(){
    return 0
}
newfact(5) // 120
fact(5) //0

函數的屬性和方法:

每一個函數都包含兩個屬性:length prototype 前者是接收參數的個數,後者是保存
全部實例方法的真正所在。
每一個函數也都包括兩個非繼承而來的方法 apply()、call(),用以改變this的指向

function sum (num1, num2){
    return num1+num2
}

function callsum(num1, num2){
    return sum.apply(this, arguments)
}

alert(callsum(10,10))  //20

基本數據類型,使用new操做符建立引用類型的實例,執行離開做用域以前一直保存在內存中,而基本數據類型,只存在代碼執行的瞬間而後當即被銷燬

1、布爾,數字,字符串

截取給定位置的那個字符 charAt 只接受一個參數

var str = 'nihao';
alert(str.charAt(1)) //i

字符串的拼接 concat 或者 + 加號操做符

var str = 'nihao';
var newstr = str.concat('world', '!');

alert(newstr) // nihao world !

字符串的截取 slice()、substr()、substring()。接收最多兩個參數

  • 一個參數的狀況:正數就不說了,對於負數最後者都會轉換爲0 前二者結果相同
  • 兩個參數的狀況:slice就不說了,substr會將第二個負數轉換爲0,substring也是將第二個負數轉換爲0,可是他會自動排序將小的位數放到前面 由(3,0)到(0,3),可是substr不會因此最後返回一個空字符串。

字符串的查找 indexOf match

var str = 'lele nihao,zheli shi di yi jia zhu';
var arr = [];
var op = str.indexOf('e');

while(op>-1){
    arr.push(op);
    op = str.indexOf('e', op+1);
}
//進入循環後每次給indexOf傳遞上一次的位置加1
alert(arr)

trim() 會建立一個字符串的副本,刪除前置及後置的全部空格

match()方法只接受一個參數 
var text = 'bat cat';
var parrent = /.at/gi;

var new = text.match(parrent)

字符串的替換 replace()

var text = 'bat cat';
var result = text.replace(/at/gi, 'oo')

字符串轉數組的方法 split()

var text = 'arr,op,kj,hg,';
var result = text.split(',')
接受第二個參數,固定數組的length

2、URL編碼方法

encodeURL() 是對整個URL進行編碼,
encodeURLComponent()對附加在現有URL後面的使用

3、 Math 對象

獲取數組中最大值和最小值 避免過多的使用循環和在if語句中肯定數值。

var val = [1,2,3,4,5,6,7,8,9];

var max = Math.max.apply(Math, val);

這個技巧的關鍵,把MAth做爲apply的第一個參數,從而正確的設置了this、
`Math.ceil() 向上取整
Math.floor() 向下取整
Math.round() 四捨五入取整`

random()方法

值 = Math.floor ( Math.round() * 可能值的總數 + 第一個可能的值 )

function round(low, up){
    var sum = up-low+1 //總數
    return Math.floor ( Math.round() *sum + low )
}

var color = ['red', 'blue', 'green', 'yellow'];
var arr = color[round(0, color.length-1)]

console.log(arr)  //多是數組中包含任意一個字符串

總結:第五章完結,在全部代碼執行以前 做用域就已經存在兩個內置對象 global和math


第六章 面向對象

  • 理解對象屬性
  • 理解並建立對象
  • 理解繼承

面向對象有類的概念,經過類能夠建立任意多個相同屬性和方法的對象。

1、建立對象

一、工廠模式,解決了建立多個類似對象的問題,卻沒有解決對象識別問題
二、構造函數,自己也是函數只不過能夠用來建立對象,缺點每一個方法都要在每一個實例上從新建立一遍,因而把函數定義轉到構造函數外面,可是若是對象定義多個方法就要定義多個全局函數,最終致使沒有封裝性。

function Person (name){
    this.name = name,
    this.sayName = function(){
        alert(this.name)
    }
}

//注意函數名大寫,是爲了區別其餘函數
//再一次提到this重定向

var o = new object();
person.call(o,"li",25,"ha");
o.sayname() //li

三、原型模式,每一個函數都有一個prototype屬性,她是一個指針,指向一個對象,實例共享。

function Person (name){
    Person.prototype.name = name,
    Person.prototype.sayName = function(){
        alert(this.name)
    }
}
var preson1 = new Person;
var preson2 = new Person;
alert(person1.sayname === person2.sayname) //true
雖然經過對象實例能夠訪問保存在原型中的值,但卻不能經過對象實例重寫原型中的值,若是同名該屬性就會屏蔽原型中的那個屬性
function Person (){
    Person.prototype.name = 'lisj',
    Person.prototype.sayName = function(){
        alert(this.name)
    }
}
var preson1 = new Person;
var preson2 = new Person;
preson1.name = 'matou'
alert(person1.name) //'matou'
alert(person2.name) //'lisj'

使用hasOwnProperty 檢測一個屬性是否存在於實例中
alert(person1.hasOwnProperty('name')) //true
alert(person2.hasOwnProperty('name')) //false

四、組合使用構造函數模式和原型模式

構造函數模式用於定義實例屬性,而原型模式用於定義方法和共享屬性

function Person (name){
    this.name = name;
    this.friends = ['ls','df']
}
Person.prototype = {
    constructor: person,
    sayname: function(){
        alert(this.name)
    }
}

var preson1 = new Person;
var preson2 = new Person;

person1.friends.push('Van')
alert(person1.friends === person2.friends) //false
alert(person1.sayname === person2.sayname) //true

2、原型鏈實現繼承,經過將一個類型的實例賦值給另外一個構造函數的原型實現


第七章函數表達式

定義函數的方式經常使用有兩種:一、函數聲明。二、函數表達式

函數聲明

function show(){}

函數表達式

var say = fuction(){}

函數聲明提早

關於函數聲明,執行代碼前會先讀取函數聲明,這就意味着先後均可以調用。

而對於函數表達式 提早調用就會報錯,使用前必須聲明。

函數表達式與函數聲明的區別

if(true){
    function say(){alert(1)}
}
else{
    function say(){alert(2)}
}

注:表面上看很合理,其實是在js中屬於無效語法,但引擎會嘗試修正此錯誤。

下面的這種寫法就很好的解決了這類問題

var say;

if(true){
     say = function(){alert(1)}
}
else{
    say = function(){alert(2)}
}

2、遞歸

遞歸函數是在一個函數經過名字調用自身的狀況下構成的

function face(num){
    if(num<=1){
        return 1;
    }
    else{
        return num* arguments.callee(num-1)
    }
}

arguments.callee 是一個指向正在執行的函數指針,用它來實現對函數的遞歸調用

也能夠經過命名函數表達式來達成相同的效果

var face = (function f(num){
    if(num<=1){
        return 1;
    }
    else{
        return num* f(num-1)
    }
})

3、閉包

有權訪問另外一個函數做用域中的變量的函數

關於閉包與變量,即閉包只能取得包含函數中任何變量的最後一個值,閉包保存的是整個變量對象而不是某個特殊的變量。

function nc(){
    var result = new Array();
    for(var i = 0;i< 10;i++){
        result[i] = function(){
            return i
        }
    }
    return result
}

能夠經過一個匿名函數強制讓閉包的行爲符合預期

function nc(){
    var result = new Array();
    for(var i = 0;i< 10;i++){
        result[i] = function(num){
            return function(){
                return num
            }
        }(i)
    }
    return result
}

關於閉包中使用this

var name = 'window'
var obj = {
    name:'lsj',
    say:function(){
        return function(){
            return this.name
        }
    }
}

alert(obj.say()()) //window
var name = 'window'
var obj = {
    name:'lsj',
    say:function(){
        var that = this;
        return function(){
            return that.name
        }
    }
}

alert(obj.say()()) //lsj

經過私有做用域模仿塊級做用域

(function(){

})();

第八章 BOM

1、最好使用settimeout 去模擬 setinterval

var num = 0;
var max = 10;

function show(){
    num++;
    if(num<max){
        settiomeout(show, 500)
    }
    else{
        alert('done')
    }
}

settiomeout(show, 500)

2、location.search 查詢字符串參數

function get(){
    var qs = (location.search.length>0? 
    location.search.substring(1):''),
    args = {},
    items = qs.length? qs.split('&'): [],
    item = =null,
    name = null,
    value = null;
    for(var i = 0;i++;i<items.length){
        item = item[i].split('=')
        name = decodeURLComponent(item[0])
        value= decodeURLComponent(item[1])
        if(name.length){
            args[name] = value
        }
    }
    return args
}

假設查詢字符串爲: ?q=javascript&num=0

var result = get()
alert(result['q']) //javascript

關於window路徑跳轉的幾種方法:

location.assign('http://nihao.com')
location.href = 'http://nihao.com'
window.location = 'http://nihao.com'

//效果相同

第十三章

  • 理解事件流
  • 使用事件處理程序
  • 不一樣的事件類型

事件流描述的是從頁面中接收事件的順序。

IE的事件流叫事件冒泡:也就是點擊事件首先在div元素上發生,再向DOM樹向上傳遞直到document對象

網景公司提出的事件流叫事件捕獲:document對象首先接收事件再從樹往下傳播到事件的實際目標

<input type="button" value="yes" onclick="alert(event.type)" />

<input type="text" value="yes" onclick="alert(this.value)" />

經過一個函數處理多個事件時,可使用type屬性

var btn = document.getElementById('de');
var handler = function(event){
    switch(event.type){
        case "click":
        alert(1);
        break;
        case "mouseover":
        alert(2);
        break;
    }
}

btn.onclick = handler
btn.onmouseover = handler

跨瀏覽器的事件對象兼容

var EventUtil = {
    getEvent:function(event){
        return event? event: window.evnet
    },
    getTarget:function(event){
        return event.target || event.srcElement
    },
    perventDefault:function(event){
        if(event.perventDefault){
            event.perventDefault()
        }
        else{
            event.returnValue = false
        }
    },
}

var a = document.getElementById('link');

a.onclick = function(event){
    event = EventUtil.getEvent(event)
    EventUtil.perventDefault(event)
}


以上代碼能夠確保全部瀏覽器中點擊該連接都會阻止默認跳轉

事件委託

創建在事件冒泡機制上的事件委託技術
只需在dom樹中最高層次添加一個事件處理程序,這種技術佔用內存少,dom引用少可以提高總體的性能。

<ul id = 'list'>
    <li id="one">one</li>
    <li id="two">two</li>
    <li id="three">three</li>
</ul>

var list = document.getElementById('list');

list.onlick = function(){
    event = EventUtil.getEvent(event)
    var target = EventUtil.getTarget(event)
    switch(target.id){
        case "one":
        alert(1);
        break;
        case "two":
        alert(2);
        break;
    }
}
相關文章
相關標籤/搜索