JavaScript之原型與原型鏈【一】

看完此篇文章你將瞭解到如下內容:前端

一、什麼是函數對象和普通對象,以及二者的關聯與異同

二、什麼是原型以及原型對象是什麼?用原型的目的

三、什麼是原型鏈,以及使用場景
複製代碼

1、函數對象和普通對象數據庫

在全部的編程語言中,萬物皆對象,JavaScript也毫無例外.在JavaScript中分爲函數對象和普通對象.Function【函數對象】、Object【普通對象】爲JavaScript自帶的對象.先從幾個例子開始入手,看下瀏覽器打印的結果是什麼:編程

function foo(){}
    var foo1=function(){}
    var foo2=new Function()
    
    var obj={}
    var obj1=new foo()
    var obj2=new Object()
    
    typeof Function //function
    typeof Object // function
    
    typeof foo //function
    typeof foo1 //function
    typeof foo2 //function
    
    typeof obj // object
    typeof obj1 // object
    typeof obj2 // object
複製代碼

從以上例子能夠看出,所謂函數對象,都是經過new Function()建立的.反過來講,凡是通new Function()建立的對象都是函數對象.除此以外,就都是普通對象.不難看出,foo,foo1,foo2,Function,Object都是函數對象.obj,obj1,obj2都爲普通對象.原型對象就是個普通對象,下面咱們來了解下什麼是原型對象...

2、原型對象後端

在JavaScript中,每當定義一個函數對象,對象中都會包含一些預約義的屬性,其中函數對象的一個屬性就是原型對象【prototype】,看個例子:瀏覽器

function Fn(){}
console.log(Fn.prototype) //Fn{}
console.log(typeof Fn.prototype) //Object
console.log(typeof Function.prototype) // Function 是個特殊的函數,由於Function是被new Function()出來的
console.log(typeof Object.prototype) // Object
console.log(typeof Function.prototype.prototype) //undefined
複製代碼

經過上面的例子能夠看出:Fn.prototype中的prototype是個隱藏的屬性,咱們在瀏覽器打印發現Fn.prototype這個原型對象中包含一個構造函數(constructor)和一個__proto__屬性,從console.log(Fn.prototype) //Fn{}能夠看出,Fn.prototype爲Fn的實例對象.在Fn建立時,建立了它的實例並賦值給它的prototype,過程基本是這樣的:bash

let fn = new Fn();
Fn.protetype =fn;
複製代碼

經過上面的過程分析,基本知道爲何Function.prototype是函數對象而不是普通對象了,看下面:編程語言

let fn = new Function();
Function.prototype = fn;
複製代碼

由於Function.prototype是Function的實例對象,而Function又是函數對象,因此Function.prototype爲函數對象.函數

知道了原型對象是什麼,下面來講下原型對象的用處.
原型對象,在JavaScript中主要目的是爲了實現繼承.【插曲:在Java或C類語言中,面向對象編程是個很好的編程思想,愈來愈多人從過程編程轉向了面向對象編程中,它容許咱們把任何事物均可以當作對象去處理,簡化了編程的複雜度、代碼的易維護性、調測的便利性以及預編譯的支持大大下降了程序的響應成本,其中面向對象--封裝、繼承、多態,就有一項叫繼承,由於JavaScript最初就被定義是個弱類型的語言,因此決定它很難像後端語言那樣實現複雜的面向對象,但隨着前端需求和業務的愈來愈複雜,急需相似後端面向對象的支持。這時候原型對象出現了,模仿類(class)的實現,以及經過原型鏈來實現繼承】(注:在 ES2015/ES6 中引 入了class關鍵字,但只是語法糖,JavaScript 仍然是基於原型的[prototype]) 來看個原型對象繼承的例子:post

function Fruit(type){
    this.type=type;
}
Fruit.prototype.getCategory=function(){
    return this.type;
}
let ty = new Fruit('蘋果');
ty.getCategory(); //蘋果
console.log('Fruit type==='+ty.getCategory());//Fruit type===蘋果
複製代碼

從例子中看出,給原型對象Fruit.prototype設置了屬性getCategory,在由Fruit實例化出來的普通對象【例:type】屬性值就被繼承過來了,如何實現繼承的,下面就要看下原型鏈了...ui

3、原型鏈

JavaScript中,當建立一個對象時,都會有一個內置的__proto__屬性,這個屬性指向建立它的函數對象的原型對象prototype,下面看下例子:

function Fruit(type){
    this.type=type;
}
Fruit.prototype.getCategory=function(){
    return this.type;
}
let ty = new Fruit('蘋果');
ty.getCategory(); //蘋果
console.log('Fruit type==='+ty.getCategory());//Fruit type===蘋果

console.log(ty.__proto__===Fruit.prototype);//true
console.log(Fruit.prototype.__proto__===Object.prototype);//true
console.log(Object.prototype.__proto__);//null
複製代碼

以上過程梳理一下:

一、普通函數:ty爲Fruit的實例化對象,這個ty裏有個內部函數屬性__proto__這個屬性指向建立它的Fruit(函數對象)的原型對象prototype
二、普通對象:Fruit.prototype內也有一個內部屬性__proto__指向建立它的Object((函數對象)的原型對象prototype
三、普通對象:Object.prototype內也有一個內部屬性__proto__但這個屬性比較特殊結果爲null;
四、以上過程就是一個原型鏈,咱們把這個以__proto__屬性串聯起來的直到Object.prototype.__proto__爲null時的鏈,叫原型鏈
複製代碼

若是你有一些關係型數據庫基礎的話,咱們也能夠把__proto__當作是外鍵,prototype爲主鍵,對象和對象之間看作是一張張表,咱們把主外鍵關聯起來,就造成了一個鏈,這樣理解起來較容易

下面咱們用一張圖,來表示這個過程:

JavaScript之淺複製與深複製【二】

歡迎關注,【前端突擊】 獵鷹突擊,迎難而上,期待你的加入...

相關文章
相關標籤/搜索