面向?qū)ο缶幊?/h1>

面向?qū)ο缶幊探榻B

面向過程

  • 概念:面向過程就是分析出解決問題所需的步驟厂僧,然后用函數(shù)把這些步驟一步一步的實現(xiàn)扣草,使用的時候再依次調(diào)用這些函數(shù)。
  • 優(yōu)點:性能比面向?qū)ο蟾撸m合跟硬件聯(lián)系很緊密的東西德召。
  • 缺點:沒有面向?qū)ο笠拙S護(hù)白魂、易復(fù)用、易擴(kuò)展上岗。

面向?qū)ο?/h4>
  • 概念:面向?qū)ο缶褪前咽聞?wù)分解成一個一個的對象福荸,然后由對象之間分工合作
  • 優(yōu)點:易維護(hù)、易復(fù)用肴掷、易擴(kuò)展敬锐,由于面向?qū)ο笥蟹庋b,繼承呆瞻,多態(tài)的特性台夺,可以設(shè)計出低耦合的系統(tǒng),使系統(tǒng)更加靈活痴脾,更加易于維護(hù)颤介。
  • 缺點:性能比面向過程低。

ES6中的類和對象

對象

  • 在JavaScript中赞赖,對象是一組無序的相關(guān)屬性和方法的集合滚朵,所有的事務(wù)都是對象,例如字符串前域,數(shù)字辕近,數(shù)組,函數(shù)等匿垄。
  • 對象是由屬性和方法組成的移宅。
    • 屬性:事物的特征,在對象中用屬性來表示椿疗。
    • 行為:事物的行為漏峰,在對象中用方法來表示。
  • 在實際開發(fā)中变丧,對象是一個抽象的概念芽狗,可以將其簡單的理解為:數(shù)據(jù)集或功能集绢掰。

  • 在ES6中增加了類的概念痒蓬,可以使用class關(guān)鍵字聲明一個類,之后用這個類來實例化對象滴劲。
  • 類抽象了對象的公共部分攻晒,它泛指某一大類。
  • 對象特指某一個班挖,通過類實例化一個具體的對象鲁捏。
  • 注意:
    • 在 ES6 中類沒有變量提升,所以必須先定義類萧芙,才能通過類實例化對象给梅。
    • 類里面的共有的屬性和方法一定要加this使用假丧。
    • 類中的 constructor 構(gòu)造函數(shù)中的 this 指向的是創(chuàng)建的實例對象。
    • 類中的方法中的this指向的是創(chuàng)建的實例對象动羽,因為是創(chuàng)建的實例對象調(diào)用了這個方法包帚,所以指向的是它的調(diào)用者。

創(chuàng)建類

  • 語法:class name {};
  • 創(chuàng)建實例:var className = new name();
  • 注意:類必須使用 new 實例化對象运吓。
  • 總結(jié):
    • 通過class關(guān)鍵字創(chuàng)建類渴邦,類名的首字母需要大寫。
    • 類中有一個constructor函數(shù)拘哨,可以接收傳遞過來的參數(shù)谋梭,同時返回實例對象。
    • constructor 這個函數(shù)只要 new 生成實例時倦青,就會自動調(diào)用這個函數(shù)瓮床,如果我們不寫這個函數(shù),類也會自動生成這個函數(shù)产镐。
    • 生成實例不能省略關(guān)鍵字 new纤垂。
    • 在創(chuàng)建類的時候,類名后面不要加小括號磷账,生成實例的時候峭沦,類名后面要添加小括號,
    • 構(gòu)造函數(shù)的時候不需要添加 function逃糟,在類中多個函數(shù)中間不需要添加逗號分隔吼鱼。
  • 代碼示例:
class Rabbit {
    constructor(type) {
        this.type = type;
    }

    spark(line) {
        // 構(gòu)造函數(shù),不需要加 function
        console.log(`The ${this.type} rabbit says '${line}'`)
    };
};
let object = new Rabbit("killer")
console.log(object)
object.spark("skr")

類中的靜態(tài)方法

  • 在ES6中绰咽,可以直接使用 static 關(guān)鍵字創(chuàng)建一個靜態(tài)方法菇肃。
  • 使用 static 關(guān)鍵字創(chuàng)建的靜態(tài)方法,方法中的類型指向的是這個對象自己取募。
<script>
    class Person {
        constructor(name) {
            this.name = name;
        }
        sayHi() {
                console.log(`${this.name}, Hi`);
            }
            // 靜態(tài)方法
        static create(name) {
            return new Person(name);
        }
    }
    const p = Person.create("tom");
    p.sayHi()
</script>

類的繼承

  • 描述:子類可以繼承父類的一些屬性和方法琐谤。
  • 語法:
class Father {}  // 父類
class Son extends Father {}  //子類繼承父類
  • 注意:
    • 繼承中,如果實例化子類輸出一個方法玩敏,先看子類有沒有這個方法斗忌,如果有就先執(zhí)行子類的。
    • 繼承中旺聚,如果子類里面沒有這個方法织阳,就去查找父類中有沒有這個方法,如果有砰粹,就執(zhí)行父類的這個方法(就近原則)唧躲。
super 關(guān)鍵字
  • super 關(guān)鍵字用于訪問和調(diào)用對象父類上的函數(shù)。可以調(diào)用父類的構(gòu)造函數(shù)弄痹,也可以調(diào)用父類的普通函數(shù)饭入。
  • 語法:
class Father {
    constructor(x, y) {
        this.x = x;
        this.y = y;
    }
    sum() {
        // console.log(this.x + this.y);
        console.log(x + y);
        }
    };

class Son extends Father {
    constructor(x, y) {
        super(x, y); // 調(diào)用父類中的構(gòu)造函數(shù)
        }
    }

// Son 繼承自父類,當(dāng)實例化 Son 類傳入?yún)?shù)的的時候肛真, Son 類中的 constructor 構(gòu)造函數(shù)會接受參數(shù)圣拄,并且將參數(shù)傳遞到 super中,進(jìn)而傳遞到父類的構(gòu)造函數(shù)中毁欣,所以可以調(diào)用父類的sum()方法庇谆,
var s = new Son(1, 2);
s.sum();
  • 繼承中,在子類中調(diào)用父類的方法凭疮,使用super.方法名()饭耳,就可以調(diào)用父類中的方法。
class Father {
    say() {
        return "這是父類";
    }
};
class Son extends Father {
    say() {
        // super.方法名 表示調(diào)用父類中的方法
        console.log(super.say() + "的子類");
    }
};
  • 在繼承中执解,子類中構(gòu)造新的方法寞肖,同時還繼承父類中的方法,此時在使用super的時候衰腌,必須在子類this之前調(diào)用新蟆。
class Father {
    constructor(x, y) {
        this.x = x;
        this.y = y;
    }
    sum() {
        console.log(this.x + this.y);
    }
};
class Son extends Father {
    constructor(x, y) {
        // super 必須在子類this之前調(diào)用
        super(x, y);

        this.x = x;
        this.y = y;
    }
    subtract() {
        console.log(this.x - this.y);
    }
};
var s = new Son(5, 3);
s.subtract();  // 2
s.sum();  // 8

構(gòu)造函數(shù)和原型

  • 在ES6之前,對象不是基于類創(chuàng)建的右蕊,而是用一種稱為構(gòu)建函數(shù)的特殊函數(shù)來定義對象和他們的特征琼稻。

構(gòu)造函數(shù)

  • 構(gòu)造函數(shù)是一種特殊的函數(shù),主要用來初始化對象饶囚,即為對象成員變量賦初始值帕翻,它總與 new 一起使用。我們可以把對象中的一些公共的屬性和方法抽取出來萝风,然后封裝到這個構(gòu)造函數(shù)中嘀掸。

  • 注意:

    • 構(gòu)造函數(shù)用于創(chuàng)建某一類對象,其首字母要大寫规惰。
    • 構(gòu)造函數(shù)要和 new 關(guān)鍵字一起使用才有意義睬塌。
  • new 在執(zhí)行時所做的四件事

    • 在內(nèi)存中創(chuàng)建一個新的空對象。
    • 讓 this 指向這個對象歇万。
    • 執(zhí)行構(gòu)造函數(shù)中的代碼揩晴,給這個新對象添加屬性和方法。
    • 返回這個新對象(所以構(gòu)造函數(shù)里面不需要return)堕花。
  • 代碼示例:

<script>
    function Start(name, age) {
        this.name = name;
        this.age = age;
        this.sing = function () {
            console.log("這是一個方法");
        }
    }

    var start = new Start();
</script>

構(gòu)造函數(shù)和實例對象的關(guān)系

  • 構(gòu)造函數(shù)是根據(jù)具體的事物抽象出來的抽象模板文狱。
  • 實例對象是根據(jù)抽象的構(gòu)造函數(shù)模板得到的具體實例對象粥鞋。
  • 每一個實例對象都有一個constructor屬性缘挽,它指向創(chuàng)建該實例對象的構(gòu)造函數(shù)。
  • 可以通過 constructor 屬性判斷實例對象和構(gòu)造函數(shù)之間的關(guān)系,但是不推薦使用這種方法壕曼,更推薦使用 instanceof 操作符苏研。

構(gòu)造函數(shù)的成員

  • JavaScript 的構(gòu)造函數(shù)中可以添加一些成員,可以在構(gòu)造函數(shù)本身添加腮郊,也可以在構(gòu)造函數(shù)內(nèi)部的 this 上添加摹蘑,通過這兩種方式添加的成員,分別稱為靜態(tài)成員實例成員轧飞。
  • 靜態(tài)成員:在構(gòu)造函數(shù)本身上添加的成員稱為靜態(tài)成員衅鹿,只能由構(gòu)造函數(shù)本身來訪問。
  • 實例成員:在構(gòu)造函數(shù)內(nèi)部創(chuàng)建的對象成員(通過this添加的成員)稱為實例成員过咬,只能由實例化的對象來訪問大渤,不可以通過構(gòu)造函數(shù)來訪問實例成員。
  • 代碼示例:
<script>
    function Start(name, age) {
        // 實例成員掸绞,只能通過構(gòu)造函數(shù)的對象來訪問泵三,不可以通過構(gòu)造函數(shù)訪問。
        this.name = name;
        this.age = age;
        this.sing = function() {
            console.log("這是一個方法");
        }
    }

    var start = new Start();
    // 靜態(tài)成員衔掸,通過構(gòu)造函數(shù)本身添加的成員烫幕。只能通過構(gòu)造函數(shù)本身來訪問,不能通過構(gòu)造函數(shù)的實例對象來訪問敞映。
    Start.sex = "男"
</script>

構(gòu)造函數(shù)存在的問題

  • 存在問題:
    • 構(gòu)造函數(shù)存在浪費內(nèi)存的問題较曼。當(dāng)構(gòu)造函數(shù)中有靜態(tài)方法的時候,當(dāng)實例化一個構(gòu)造函數(shù)振愿,會在內(nèi)存中開辟一個新的內(nèi)存空間诗芜,此時會根據(jù)構(gòu)造函數(shù)中的靜態(tài)方法,再次開辟新的內(nèi)存空間埃疫,所以會造成內(nèi)存空間浪費的問題伏恐。
    • 解決方法:使用構(gòu)造函數(shù)的原型對象

構(gòu)造函數(shù)原型

  • 構(gòu)造函數(shù)原型 prototype

    • 每一個構(gòu)造函數(shù)都有一個原型 prototype 屬性,指向另一個對象栓霜,這個prototype就是一個對象翠桦,這個對象的所有屬性和方法,都會被構(gòu)造函數(shù)所擁有胳蛮。
    • 我們可以把一些不變的方法销凑,直接定義在prototype對象上,這樣所有對象的實例就可以共享這個方法仅炊。
    • 一般情況下斗幼,我們會將公共的屬性定義到構(gòu)造函數(shù)里面,公共的方法會放到原型對象身上抚垄。
  • 代碼示例

<script>
    function Start(name, age) {
        this.name = name;
        this.age = age;
    };
    Start.prototype.sing = function() {
        console.log("這是定義在prototype對象中的公共方法");
    }

    var start = new Start();
    start.sing()
</script>
對象原型 _proto_
  • 所有的對象都會有一個屬性__proto__蜕窿,它是一個指針谋逻,指向構(gòu)造函數(shù)中的protottype原型對象,之所有我們對象可以使用構(gòu)造函數(shù)中的prototype原型對象的屬性和方法桐经,就是應(yīng)為有__proto__原型的存在毁兆。
  • 對象身上系統(tǒng)添加了一個__proto__屬性,指向我們構(gòu)造函數(shù)的原型對象阴挣。
  • __proto__ 對象原型和原型對象 prototyte 是等價的气堕。
  • __proto__ 對象原型的意義就在于為對象的查找機(jī)制提供一個方法,或者說一條路線畔咧,但是他是一個非標(biāo)準(zhǔn)屬性茎芭,因為實際開發(fā)中,不可以使用這個屬性誓沸,它只是內(nèi)部指向原型對象 prototype骗爆。
constructor 構(gòu)造函數(shù)

對象原型(__proto__)和構(gòu)造函數(shù)(prototype)原型對象里面都有一個 consturctor 屬性,consturctor我們稱為構(gòu)造功函數(shù)蔽介,因為他返回構(gòu)造函數(shù)本身摘投。
consturctor主要用于記錄該對象引用了那個構(gòu)造函數(shù),它可以讓原型對象重新指向原來的構(gòu)造函數(shù)虹蓄。

構(gòu)造函數(shù)犀呼、實例、原型對象三者之間的關(guān)系

  • 構(gòu)造函數(shù)有一個屬性prototype薇组,屬性值是prototype原型對象
  • 原型對象prototype中有一個 consturctor 屬性外臂,它的屬性值是構(gòu)造函數(shù)本身。
  • 通過 new 創(chuàng)建的實例對象律胀,有一個 __proto__ 屬性宋光,它是一個指針,指向的是構(gòu)造函數(shù)中的 prototype 屬性炭菌。但是他是一個非標(biāo)準(zhǔn)的屬性罪佳,所以在實際開發(fā)中一般不寫這個屬性名,而是直接使用它指向的 prototype 中的方法黑低。所以可以直接使用通過 實例對象打點調(diào)用 構(gòu)造函數(shù)中 prototype 中的方法赘艳。

解決構(gòu)造函數(shù)內(nèi)存浪費的方法

  • JavaScript規(guī)定,每一個構(gòu)造函數(shù)都有一個 prototype 屬性克握,指向構(gòu)造函數(shù)的原型對象蕾管,這個原型對象中所擁有的屬性和方法,都會被構(gòu)造函數(shù)的實例對象所擁有菩暗。因為實例對象 __proot__ 屬性的存在掰曾。
  • 因此我們可以把所有對象實例所需要共享的屬性和方法直接定義在prototype對象上,以此來解決內(nèi)存浪費問題停团。

原型鏈查找機(jī)制

  • 當(dāng)實例對象調(diào)用構(gòu)造函數(shù)中的方法的時候旷坦,首先會看實例對象本身是否具有該方法掏熬,如果有,就執(zhí)行實例對象身上的方法契讲。
  • 如果實例對象本身沒有要執(zhí)行的方法铅歼,因為有 __proto__ 屬性的存在,會指向到構(gòu)造函數(shù)中的 prototype 對象,就會去構(gòu)造函數(shù)中的 prototype 對象中查找要執(zhí)行的方法容达。

實例對象讀寫原型對象成員

讀取:

  • 先在自己身上找测砂,找到即返回苇羡。
  • 如果在自己身上找不到,就會沿著原型鏈向上查找婉烟,找到即返回娩井。
  • 如果一直查找到原型鏈的末端還沒有找到,則返回undefined似袁。

添加:

  • 通過實例對象打點的方式添加新成員洞辣,會直接添加給自己,會屏蔽對原型對象的訪問昙衅。
  • 如果通過實例對象直接打點修改原型對象上的屬性和方法的時候扬霜,也是會直接添加給自己,屏蔽掉對原型對象的訪問而涉。
  • 更改復(fù)雜數(shù)據(jù)內(nèi)容的時候著瓶,則會按照原型鏈的查找機(jī)制進(jìn)行查找數(shù)據(jù)和更改。比如原型對象中有一個 address 屬性啼县,他的屬性值是一個對象材原,對象中有 city屬性,通過是對象打點修改city屬性的時候季眷,會按照原型鏈的查找機(jī)制查找該屬性余蟹,如果能夠查到就進(jìn)行修改,如果查到就返回一個undefined子刮。

實例代碼:

function Person(name, age) {
    this.name = name;
    this.age = age;
};
Person.prototype.type = "human";
Person.prototype.address = {
    "city": "北京"
};
var p = new Person("mike", 20);

// 修改type屬性
p.type = "dog";  // 不會修改原型對象中的type屬性客叉,會在構(gòu)造函數(shù)中添加一個type的屬性,屬性值為dog
// 添加屬性
p.sex = "man"; // 直接在構(gòu)造函數(shù)中添加一個sex屬性话告,屬性值為 man兼搏。
// 修改復(fù)雜的屬性
p.address.city = "上海";  // 會按照原型鏈的查找機(jī)制,在原型對象中找到address屬性沙郭,并且修改其中的city屬性佛呻。

原型對象添加屬性和方法的簡單語法

  • 像原型對象中Tina加屬性和方法可以通過 構(gòu)造函數(shù).prototype.屬性/方法() 的方式添加,如果有多個屬性和放發(fā)的話病线,就會添加書寫多次吓著。為了減少不必要的輸入鲤嫡,可以通過對象字面量的方法重寫原型對象。將構(gòu)造函數(shù).prototype重置到一個新的對象绑莺。
  • 注意:重寫原型對象會丟失constructor屬性暖眼,所以需要手動將constructor指向正確的構(gòu)造函數(shù)。
  • 代碼實例
  • 一般在定義構(gòu)造函數(shù)的時候纺裁,可以根據(jù)成員的功能不同诫肠,分別進(jìn)行設(shè)置:
    • 私有成員(一般是非函數(shù)):放到構(gòu)造函數(shù)中。
    • 共享成員(一般就是函數(shù)):放到原型對象中欺缘。
function Person(name, age) {
    this.name = name;
    this.age = age;
};

// 重寫構(gòu)造函數(shù)中的原型對象栋豫。
Person.prototype = {
    // 注意將 constructor 指向正確的構(gòu)造函數(shù)。
    constructor: Person,
    type : "human",
    sayName : function() {
        console.log(this.name);
    }
};

var p = new Person("mike", 20);

對象中的繼承

構(gòu)造函數(shù)的屬性繼承

  • 對象中的屬性繼承可以通過在子類中通過call()方法調(diào)用父類谚殊,通過改變 this 的指向丧鸯,將父類中的參數(shù)傳遞到子類中,完成對象中的屬性的繼承嫩絮。
  • 示例代碼:
<script>
    // 父類構(gòu)造函數(shù)
    function Person(name, age, sex) {
        this.name = name;
        this.age = age;
        this.sex = sex;
    };
    // 子類構(gòu)造函數(shù)
    function Student(name, age, sex, score) {
        // 通過 call() 方法調(diào)用父類構(gòu)造函數(shù)丛肢,call() 方法中傳遞的this指向通過 new 關(guān)鍵字調(diào)用 Student 構(gòu)造函數(shù)時候生成的實例對象
            // 所以當(dāng)通過 new 關(guān)鍵字 調(diào)用構(gòu)造函數(shù)的時候,Person 構(gòu)造函數(shù)中指向的this是指向的 Student 實例對象
            // 所以 Student 構(gòu)造函數(shù)中 包含 父類構(gòu)造函數(shù)中的屬性剿干。
        Person.call(this, name, age, sex);
        this.score = score
    };
    console.log(new Student("zs", 18, "男", 100))
    // 返回一個Student對象蜂怎,對象中包含 name, age,sex, score屬性
    </script>

構(gòu)造函數(shù)中的方法繼承

  • 在子類的原型對象上,繼承父類原型對象的方法可以通過對象拷貝繼承和原型繼承兩種方法進(jìn)行繼承怨愤。

  • 方法一:對象拷貝繼承

    • 通過對象拷貝的方法實際上通過for in 循環(huán)派敷,將父類構(gòu)造函數(shù)中的 perototype 對象中的方法賦值到 子類的 perototype 對象中,但是在繼承的時候需要注意不能繼承 父類的 constructor撰洗。
  • 方法二:原型繼承

    • 原型繼承實際是讓子類實例對象的prototype對象指向父類的實例對象篮愉,當(dāng)在子類中調(diào)用父類的方法的時候,會先在子類中查找該方法差导,如果子類中沒有該方法试躏,則會通過原型鏈查找原型對象中的方法。所以可以繼承父類的方法设褐。
    • 需要注意的是颠蕴,當(dāng)使用原型繼承的時候,需要重新修改子類的constructor 屬性助析,因為如果修改子類的原型對象為父類的實例對象犀被,則只有父類中的constructor,并且指向的是父類的構(gòu)造函數(shù)外冀。所以需要自己添加寡键。
  • 實例代碼:

 <script>
    function Person(name, age, sex) {
        this.name = name;
        this.age = age;
        this.sex = sex;
    };
    Person.prototype.sayHi = function() {
        console.log("Hi");
    };

    function Student(name, age, sex, score) {
        // 繼承父類的屬性
        Person.call(this, name, age, sex);
        // 設(shè)置自己的屬性
        this.socre = score;
    };
    // 繼承父類的方法一:對象拷貝繼承
    // for (let key in Person.prototype) {
    //     if (key === "constructor") {
    //         continue;
    //     };
    //     Student.prototype[key] = Person.prototype[key];
    // };
    // 繼承父類方法二:原型繼承
    Student.prototype = new Person();
    Student.prototype.constructor = Student;

    let s = new Student();
    console.log(s);
</script>

通過構(gòu)造函數(shù)定義 函數(shù)

  • 函數(shù)本身也是一種對象,可以調(diào)用屬性和方法雪隧∥餍可以使用 Function 構(gòu)造函數(shù)员舵,通過 new 關(guān)鍵字的方法定義一個函數(shù)。
  • 語法:let fun = new Function("參數(shù)1", "參數(shù)2")
  • 參數(shù):通過構(gòu)造函數(shù)定義的函數(shù)藕畔,在傳遞參數(shù)的時候马僻,如果函數(shù)本身需要有參數(shù)傳遞,則在構(gòu)造函數(shù)中前面 參數(shù)1 的地方傳遞參數(shù)注服,如果需要傳遞多個參數(shù)韭邓,則依次在后面?zhèn)鬟f。如果函數(shù)本身不需要參數(shù)祠汇,則在構(gòu)造函數(shù)中只需要傳遞一個函數(shù)執(zhí)行式仍秤。注意熄诡,不管構(gòu)造函數(shù)中傳遞了多少參數(shù)可很,最后一個參數(shù)始終是函數(shù)的執(zhí)行式。
  • 實例代碼:
let fun = new Function("a", "b", "let a = 1; console.log(a + b)")
fun("3", "4");
// 輸出結(jié)果:"14"

函數(shù)調(diào)用和 this 指向

  • 普通函數(shù)凰浮,通過給函數(shù)名或者變量名添加 () 方式執(zhí)行我抠。
  • 函數(shù)中的 this,默認(rèn)指向的是 window 對象袜茧。
function fun () {
    console.log("1");
};
  • 構(gòu)造函數(shù)菜拓,通過 new 關(guān)鍵字進(jìn)行調(diào)用。
  • 構(gòu)造函數(shù)中的 this笛厦,指向的是調(diào)用構(gòu)造函數(shù)的實例對象纳鼎。
function Person(name) {
    this.name = name;
};
let p = new Person("js");
  • 對象中的方法,通過對象打點調(diào)用函數(shù)裳凸,然后加小括號贱鄙。
  • 內(nèi)部的this 默認(rèn)指向的是調(diào)用的對象自己。
let o = {
    sayHi = function() {
        console.log("Hi");
    };
};
  • 事件函數(shù)姨谷,不需要加特殊的符號逗宁,只要事件被觸發(fā),會自動執(zhí)行函數(shù)梦湘。
  • 事件函數(shù)的內(nèi)部瞎颗,this 指向的是調(diào)用事件函數(shù)的事件源。
document.onclick = function () {
    console.log("事件函數(shù)")
};
  • 定時器和延時器中的函數(shù)捌议,不需要加特殊的符號哼拔,只要執(zhí)行后,在規(guī)定的時間自動執(zhí)行瓣颅。
  • 定時器和延時器中的 this倦逐,默認(rèn)指向的是 window 對象。
setInterval(function() {
    console.log("定時器")
}, 1000);
  • 注意:this 的指向是需要聯(lián)系執(zhí)行的上下文弄捕,在調(diào)用的時候僻孝,是按照什么方式調(diào)用导帝,指向是不一樣的。例如在外部定義了一個普通函數(shù)穿铆,在對象中創(chuàng)建了一個方法您单,屬性值是外部定義的函數(shù),當(dāng)通過對象調(diào)用方法的時候荞雏,此時這個函數(shù)中的this指向就是這個調(diào)用對象自己本身虐秦。

函數(shù)中的方法

call 方法

  • call 方法可以指定函數(shù)的this,并且可以執(zhí)行函數(shù)并傳參凤优。
  • 參數(shù):第一個參數(shù)悦陋,傳入一個指定讓 this 指向的對象,第二個參數(shù)及以后筑辨,是參數(shù)本身所需的函數(shù)俺驶。
  • 語法:函數(shù)名.call(參數(shù)1, 參數(shù)2, 參數(shù)n)
  • 返回值:返回函數(shù)自己本身的返回值。
  • 代碼示例
function fun(a, b) {
    console.log(this);
    console.log(a + b)
};
o = {name: "zs"};
fun.call(o, 1,2)
// 輸出結(jié)果 this 指向 o棍辕,返回結(jié)果是3

應(yīng)用場景:利用數(shù)組中的push方法暮现,實現(xiàn)讓對象動態(tài)添加元素。

<script>
    // 利用 call 方法楚昭,實現(xiàn) object 對象使用 push 方法
    let o = {
        0: 10,
        length: 1
    };
    // 調(diào)用數(shù)組中的push方法栖袋,使用call方法修改 this 指向
    Array.prototype.push.call(o, 20);
    console.log(o);
</script>

apply 方法

  • call 方法可以指定函數(shù)的this,并且可以執(zhí)行函數(shù)并傳參抚太。
  • 參數(shù):第一個參數(shù)塘幅,傳入一個指定讓 this 指向的對象,第二個參數(shù)是函數(shù)的參數(shù)組成的數(shù)組尿贫,只能傳遞兩個參數(shù)电媳。
  • 返回值:返回函數(shù)自己本身的返回值。
  • 代碼示例
function fun(a, b) {
    console.log(this);
    console.log(a + b)
};
o = {name: "zs"};
fun.apply(o, [1,2])
// 輸出結(jié)果 this 指向 o帅霜,返回結(jié)果是3

bind 方法

  • call 方法可以指定函數(shù)的this匆背,bind 方法不能執(zhí)行函數(shù),但是可以傳遞函數(shù)方法的參數(shù)
  • 參數(shù):第一個參數(shù)身冀,傳入一個指定讓 this 指向的對象钝尸,第二個參數(shù)是函數(shù)執(zhí)行所需要的的參數(shù)。如果在執(zhí)行 bind 方法的時候沒有傳遞函數(shù)本身執(zhí)行所需要的參數(shù)搂根,在調(diào)用新的返回函數(shù)體的時候珍促,也可以繼續(xù)傳遞參數(shù)。
  • 返回值:返回一個新的指定了 this 的函數(shù)剩愧,也可以叫綁定函數(shù)猪叙。
  • 代碼示例
function fun(a, b) {
    console.log(this);
    console.log(a + b)
};
o = {name: "zs"};
let fn = fun.bind(o,2, 3);
fn();
// 在執(zhí)行fn的時候也可以傳遞參數(shù),如果在使用bind方法的時候傳遞了函數(shù)所需要的參數(shù),在執(zhí)行返回結(jié)果的時候傳遞參數(shù)不會覆蓋掉之前傳遞的參數(shù)穴翩,相當(dāng)于給執(zhí)行函數(shù)傳遞在參數(shù)后面又新增了參數(shù)犬第,也可以在使用bind方法的時候傳遞一部分參數(shù),然后在調(diào)用返回結(jié)果的時候再傳遞剩余參數(shù)芒帕。
// 輸出結(jié)果 this 指向 o歉嗓,返回結(jié)果是5

高階函數(shù)

  • 描述:如果一個函數(shù)作為其他函數(shù)的參數(shù)或者返回值,那么稱之為高階函數(shù)背蟆。

閉包

  • 函數(shù)在定義的時候鉴分,能夠記住自己生成的作用域環(huán)境和函數(shù)自己,將他們形成一個封閉的環(huán)境带膀,這就是閉包志珍。不論函數(shù)以任何方式任何地方進(jìn)行調(diào)用,都會回到自己定義時的密閉環(huán)境進(jìn)行執(zhí)行垛叨。
  • 從廣義上來說伦糯,定義在全局的函數(shù)也是一個閉包,只是沒有辦法將這樣的函數(shù)拿到更外面的作用域進(jìn)行調(diào)用点额,從而觀察閉包的特點舔株。
  • 閉包是天生存在的莺琳,不需額外的結(jié)構(gòu)还棱。

閉包的用途

  • 可以再函數(shù)外部讀取函數(shù)內(nèi)部的成員。
  • 讓函數(shù)內(nèi)成員始終存活在內(nèi)存中惭等。
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者

  • 序言:七十年代末珍手,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子辞做,更是在濱河造成了極大的恐慌琳要,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,755評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件秤茅,死亡現(xiàn)場離奇詭異稚补,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)框喳,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評論 3 395
  • 文/潘曉璐 我一進(jìn)店門课幕,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人五垮,你說我怎么就攤上這事乍惊。” “怎么了放仗?”我有些...
    開封第一講書人閱讀 165,138評論 0 355
  • 文/不壞的土叔 我叫張陵润绎,是天一觀的道長。 經(jīng)常有香客問我,道長莉撇,這世上最難降的妖魔是什么呢蛤? 我笑而不...
    開封第一講書人閱讀 58,791評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮棍郎,結(jié)果婚禮上顾稀,老公的妹妹穿的比我還像新娘。我一直安慰自己坝撑,他們只是感情好静秆,可當(dāng)我...
    茶點故事閱讀 67,794評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著巡李,像睡著了一般抚笔。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上侨拦,一...
    開封第一講書人閱讀 51,631評論 1 305
  • 那天殊橙,我揣著相機(jī)與錄音,去河邊找鬼狱从。 笑死膨蛮,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的季研。 我是一名探鬼主播敞葛,決...
    沈念sama閱讀 40,362評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼与涡!你這毒婦竟也來了惹谐?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,264評論 0 276
  • 序言:老撾萬榮一對情侶失蹤驼卖,失蹤者是張志新(化名)和其女友劉穎氨肌,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體酌畜,經(jīng)...
    沈念sama閱讀 45,724評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡怎囚,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,900評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了桥胞。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片恳守。...
    茶點故事閱讀 40,040評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖埠戳,靈堂內(nèi)的尸體忽然破棺而出井誉,到底是詐尸還是另有隱情,我是刑警寧澤整胃,帶...
    沈念sama閱讀 35,742評論 5 346
  • 正文 年R本政府宣布颗圣,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏在岂。R本人自食惡果不足惜奔则,卻給世界環(huán)境...
    茶點故事閱讀 41,364評論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望蔽午。 院中可真熱鬧易茬,春花似錦、人聲如沸及老。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,944評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽骄恶。三九已至食铐,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間僧鲁,已是汗流浹背虐呻。 一陣腳步聲響...
    開封第一講書人閱讀 33,060評論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留寞秃,地道東北人斟叼。 一個月前我還...
    沈念sama閱讀 48,247評論 3 371
  • 正文 我出身青樓,卻偏偏與公主長得像春寿,于是被迫代替她去往敵國和親朗涩。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,979評論 2 355

推薦閱讀更多精彩內(nèi)容