180331 原型

  • 原型是function對象的一個屬性,它定義了構造函數製造出的對象的公共祖先。
  • 通過該構造函數產生的對象,可以繼承該原型的屬性和方法。
  • 原型也是對象。
  • 原型就像是批處理添加水印:預設好的統一處理,有顏色主題不合適的單獨設計。

  • 訪問對象的屬性,如果本身沒有,會向原型上面找。

  • 由構造函數創建的對象,有隠式屬性this對象。

  • this對象有一個屬性 _ proto_ [指針,指向對象的原型]

  • this . _ proto_ = Function.prototype

  • 由構造函數創建的對象的屬性[this]的屬性[_ proto_]的值等於構造函數的屬性[prototype]的值。

  • 這兩個指向的值是一個對象,即原型對象。

obj.attributes 
-> 
if(obj.attributes){return obj._proto_.attributes}

原型應用:

CarFactory.prototype.door = 4;
CarFactory.prototype.distance = 0;
CarFactory.prototype.run = function() {
    this.distance += 100;
}
CarFactory.prototype.aurhor = {
        name: 'cst',
        money: 999999
    }
    //提取全部實例的公共特點,添加到遠行對象裏
    //相當於給每一個實例初始化,添加水印,節約性能

function CarFactory(wheelNum, carColor) {
    this.wheel = wheelNum;
    this.color = carColor;
}
var oCar1 = new CarFactory(3, 'red');
var oCar2 = new CarFactory(5,'yellow');
        oCar1.door = 6;
// 實例本身新增door屬性,就不會找原型,也不會影響原型和其他實例
console.log(oCar.door);

delete oCar1.chair; // true 刪除不存在的屬性

oCar1.author.money = 200;
console.log(oCar2.author.money);   // 改變實例本身屬性,還是改變原型屬性

[改變原型對象的指向] 和 [改變原型對象內的值]

CarFactory.prototype.door = 4;
var oCar1 = new CarFactory();
CarFactory.prototype = {
    door:6;   //已經創建好的對象不會被新改變的原型影響
}

// this._proto_ --鏈接-- Function.prototype
// 這兩個值對應的是一個對象,過程是F.p把地址給了t._p_
// 當改變了F.p,它會指向一個新的對象,有一個新的地址
// 而t._p_還是以前的地址
// 兩個值不是時刻牽引的,是一次性賦給相同地址,之後撒手
// 讓F.p等於一個新對象,相當於斷開了與t._p_的聯繫與羈絆
// 讓F.p.attributes等於一個新的值,並沒有斷開兩者的聯繫,
// 因此會出現給F.p賦值新對象不會影響已經創建的對象
// 而給F.p賦值新的屬性值,會影響已經創建的對象
// 因爲聯繫還在,f._p_是跟着對象走的
// 兩個都是屬性名而已,兩張入場券,進入同一個地方,這個地方里面存着原型信息
// 要在一張入場券上增加或修改演員,要麼把入場券引向別的場次
// 跟對象直接聯繫的是__proto__,只要看它的值就行了,是保持鏈接屬性更新。
// 還是斷開鏈接,屬性不變

var PrototypeSelf = {name:'cst'};
var __proto__Self = PrototypeSelf;
PrototypeSelf = {name:'duyi'};
__Proto__Self.name  // -> cst

練習

Person.prototype.name = 'sunny';

function Person() {}
var oPerson = new Person();
Person.prototype.name = 'cherry';
console.log(oPerson.name); // cherry


//======================================


Person.prototype.name = 'sunny';

function Person() {}
Person.prototype.name = 'cherry';
var oPerson = new Person();
console.log(oPerson.name); // cherry


//======================================


Person.prototype.name = 'sunny';

function Person() {}
var oPerson = new Person();
Person.prototype = {
    name: 'cherry'
};
console.log(oPerson.name); // sunny

//=======================================

Person.prototype.name = 'sunny';

function Person() {}
Person.prototype = {
    name: 'cherry'
};
var oPerson = new Person();
console.log(oPerson.name); // cherry

查詢對象構造函數

object.prototype

原型鏈

GrandFather.prototype.lastName = 'yang';

function GrandFather() {
    this.bike = 1;
}
Father.prototype = new GrandFather();

function Father() {
    this.fortune = {
        money: 999999,
        house: 4
    }
    this.name = 'jaja'
}
Son.prototype = new Father();

function Son() {
    this.name = 'heihei',
        this.age = 20
}

var oSon = new Son();
console.log(oSon.lastName);

oSon.fortune.house += 1;  //訪問fortune對象的屬性並賦值,改變相同地址的引用值, 相當於改變原型上的屬性
oSon.fortune = {};       //將fortune屬性指向另一個對象地址,換了一個引用值, 相當於給oSon自己添加屬性

var oSon2 = new Son();
console.log(oSon2.fortune.house);   //  5  這個是引用值,後續會受影響  

這裏寫圖片描述

  • 除(object.create()創建的對象之外),沿着原型鏈一直向上遊查詢,找到頭都是object.prototype -> {}
  • 函數的原型對象constructor默認指向函數本身,原型對象除了有原型屬性外,爲了實現繼承,還有一個原型鏈指針proto,該指針指向上一層的原型對象,而上一層的原型對象的結構依然類似,這樣利用proto一直指向Object的原型對象上,而Object的原型對象用Object.prototype.proto = null表示原型鏈的最頂端,如此變形成了javascript的原型鏈繼承,同時也解釋了爲什麼所有的javascript對象都具有Object的基本方法。
    這裏寫圖片描述

原型方法的重寫

如果原型鏈中上游已經有一個函數,可以在下游重新定義。

改變this指向

function.call(host,num1,num2)
function.apply(host,[num1,num2])

function test(){
    console.log(this);
}
test();   //thiswindow

相當於window.test.call(window);

function.call(調用者)
function Person(name, age) {
    this.name = name;
    this.age = age;
}

function Student(name, age, myClass, myGrade) {
    Person(); // !!沒有寫出來是誰調用的,都是window調用
    Person.call(this, name, age); // Studnet函數調用Person函數,保證Person函數的參數
} // call(name,age)->Student(name,age)->Student(實參)
// this是當前調用的函數Student
new Student('cst', 18, 2, 4); //構造函數會在內部隠式創建this對象並返回,
//原因是構造函數本身就是用於創建對象並初始化
//構造函數身份象徵:new

var numObj = {
    x: 1,
    y: 2
}

function add(a, b) {
    console.log(this.x + a + this.y + b);
}
add(); // NaN
add.call(numObj, 3, 4); // 10

繼承

聖盃模式:閉包

var inherit = (function() {
    var Cache = function() {}; //緩存函數,每次執行都需要創建一個,沒有必要,寫入閉包
    return function(Target, Origin) {
        Cache.prototype = Origin.prototype; //下游不影響上游
        Target.prototype = new Cache();
        Target.prototype.constructor = Target;
        Target.prototype.uber = Origin;
    }
})();

這裏寫圖片描述


防止變量污染

立即執行函數

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章