《精通JavaScript》讀書筆記

weixin_33807284發表於2016-07-12

圖片發自簡書App

1.使用建構函式屬性來判斷物件的型別

//檢查數字實際上是否為字串
if (num.constructor == String) {
    //如果是,則把字串解析為整數
    num = parseInt(num);
}
//檢查字串實際上是否為陣列
if (str.constructor == Array) {
    //如果是,則根據陣列用逗號歸併出字串來
    str = str.join(',');
}

2.變數的型別檢查

變數 typeof變數 變數.建構函式
{an:"object"} object Object
["an","array"] object Array
function(){} function Function
"a string" string String
55 number Number
true boolean Boolean
new User() object User

3. 用閉包實現的函式Curry化

//數字求和函式的函式生成器
function addGenerator(num) {
    //返回一個簡單的函式,求兩個數字的和,其中第一個數字來自生成器
    return function (toAdd) {
        return num + toAdd
    }
}
//addFive現在包含一個接受單一引數的函式,這個函式能求得5加上該引數的和
var addFive = addGenerator(5);
console.log(addFive(4));//輸出9

4.使用匿名函式來隱藏全域性作用域變數

(function(){
    //變數原本應該是全域性的
    var msg = "test";
    //將一個新函式繫結到全域性物件
    window.onunload = function(){
        //這個函式使用了隱藏的msg
        alert(msg);
    };
    //關閉匿名函式並執行
})();

5.使用匿名函式來激發出建立多個使用閉包的函式所需的作用域

//一個ID為main的元素
var obj = document.getElementById("main");
//用於繫結一個陣列
var items = ["click", "keypress"];
//遍歷陣列的每個成員
for (var i = 0; i < items.length; i++) {
    //使用一個自執行的匿名函式來激發出作用域
    (function () {
        //記住在這個作用域內的值
        var item = items[i];
        obj["on" + item] = function () {
            /item引用本for迴圈上下文所屬作用域中的一個父變數
            alert("alert" + item);
        }
    })();
}

6.在上下文物件內使用函式並將其上下文物件切換為另一個變數

var obj = {
    yes: function () {
        //this==obj
        this.val = true;
    },
    no: function () {
        this.val = false;
    }
};

//我們發現'obj'物件沒有val屬性
alert(obj.val == null);

//執行yes函式後,將val屬性與'obj'物件關聯起來
obj.yes();
alert(obj.val == true);

//不過現在把window.no指向obj.no並執行之
window.no = obj.no;
window.no();

//結果是obj物件的val不變(因為no的上下文已經變為window物件了)
alert(obj.val == true);

//而window的val屬性被更新了
alert(window.val == false);

把obj.no變數的上下文物件切換為window變數時,程式碼變得不好理解了。幸運的是,JavaScript提供了一套方法來讓這一過程變得更好理解和實現。即call和apply兩個方法。

7.修改函式上下文物件的例子

//一個設定上下文物件顏色樣式的簡單函式
function changeColor(color) {
    this.style.color = color;
}

//在window物件中呼叫此函式會失敗,因為window物件沒有style屬性
changeColor("white");

//找出ID為main的文件
var main = document.getElementById("main");

//使用call方法將它的顏色置為黑色
changeColor.call(main, "black");

//設定body元素顏色的函式
function setBodyColor() {
    //apply方法將上下文物件設定為第一個引數指定的body元素,第二個引數是傳給函式的所有引數的陣列
    changeColor.apply(document.body, arguments);
}

//將body的背景色置為黑色
setBodyColor("black");

8.使用constructor屬性的例子

//建立一個新的簡單的User物件
function User() {
}

//建立一個User物件
var me = new User();

//還是建立一個新的User物件(用前一個物件的constructor引用來建立)
var you = new me.constructor();

//你可以發現這兩個物件的constructor實質上是一致的
alert(me.constructor == you.constructor);

9.物件的方法通過prototype物件新增的例子

//建立一個新的User建構函式
function User(name, age) {
    this.name = name;
    this.age = age;
}

//將一個新的函式新增到此物件的prototype物件中
User.prototype.getName = function () {
    return this.name;
};

//並再給此prototype物件新增一個函式,注意其上下文是例項化後的物件
User.prototype.getAge = function () {
    return this.age;
};

//例項化一個新的User物件
var user = new User("Bob", 44);

//可以看到我們新增的這兩個屬性都在剛才建立的物件中,並且有合適的上下文
alert(user.getName == "Bob");
alert(user.getAge == 44);

10.私有方法

私有方法和私有變數只允許其他的私有方法、私有變數和特權方法訪問。這種方法可以定義一些只讓物件內部訪問,而外部訪問不到的程式碼。
//表示教室的一個物件建構函式
function Classroom(students, teacher) {
    //用於顯示所有班上學生的私有方法
    function disp() {
        alert(this.names.join(","));
    }

    //將班級資料存入公共物件屬性中
    this.students = students;
    this.teacher = teacher;

    //呼叫私有方法來顯示錯誤
    disp();
}

//建立一個新的classroom物件
var c = new Classroom(["John", "Bob"], "Mr. Smith");

//呼叫disp方法會失敗,因為它不是該物件的公共屬性
c.disp();

11.特權方法

特權方法用來指代哪些在檢視並處理私有變數的同時允許使用者以公共方法的方式訪問的方法。
//建立一個新的User物件建構函式
function User(name, age) {
    //嘗試算出使用者出生的年份
    var year = (new Date()).getFullYear() - age;

    //建立一個新的特權方法,能夠訪問year變數,同時自身屬於公共可訪問的
    this.getYearBorn = function () {
        return year;
    }
}

//建立User物件的一個新示例
var user = new User("Bob", 44);

//驗證返回的年份正確
alert(user.getYearBorn() == 1962);

//注意我們無法訪問該物件私有的年份屬性
alert(user.year == null);

12.靜態方法

靜態方法的實質與任何其他一般函式沒有什麼不同,最主要的區別在於,其他函式是以物件的靜態屬性形式存在的。作為一個屬性,它們不能在該物件的例項的上下文中訪問,而只屬於主物件本身的那個上下文中。
//新增到一個User物件的靜態方法
User.clnoeUser = function (user) {
    //建立並返回一個新的使用者
    return new User(user.getName(), user.getAge());
};

13.原型式繼承的例子

//為Person物件建立一個建構函式
function Person(name) {
    this.name = name;
}

//給Person物件新增一個新方法
Person.prototype.getName = function () {
    return this.name;
};

//建立一個新的User物件的建構函式
function User(name, password) {
    //注意,這裡並沒有支援方法的過載/整合,也就是說,不能呼叫父類的建構函式
    this.name = name;
    this.password = password;
}

//User物件繼承所有Person物件的方法
User.prototype = new Person();

//我們新增一個新方法到User物件中
User.prototype.getPassword = function () {
    return this.password;
};

14.JavaScript中的名稱空間化及其實現

//建立一個預設的、全域性的名稱空間
var YAHOO = {};

//使用物件設定一些子名稱空間
YAHOO.util = {};

//建立最終名稱空間,它包含一個值為函式的屬性
YAHOO.util.Event = {
    addEventListener: function () {

    }
};

//呼叫某個具體名稱空間中的函式
YAHOO.util.Event.addEventListener();

相關文章