1. 程式人生 > >JavaScript的原型和原型鏈 (一)

JavaScript的原型和原型鏈 (一)

關於js的原型和原型鏈,有人覺得這是很頭疼的一塊知識點,相較於普通語法,它更難以理解一些,在開發上也較不常見。但這並不意為這它不重要,相反,它很重要。要了解原型和原型鏈,我們得先從物件說起

建立物件

通過物件字面量

通過物件直接量建立物件,這是最簡單也是最常用的建立物件的方式

let obj= {};
let LJJ = {name: "劉家軍",age: 21};
let YH = {name: "袁姮",age: LJJ.age + 1};

通過new建立物件

通過new運算子建立並初始化一個新物件,關鍵字new後跟隨一個函式呼叫,這個函式成為建構函式(constructor),建構函式用來初始化一個新物件,js包含了一些內建的建構函式

let  obj = new Object()//建立一個空物件等同於 let obj = {}
let  arr = new Array()//建立一個空陣列等同於 let arr = []

上面的Object(),Array(),都是js內建的建構函式
除了內建的建構函式,我們還可以使用自定義建構函式來初始化物件

function fun(){
    console.log("這是一個自定義建構函式")
};
let myFun= new fun();

通過Object.create()

Object.create(proto, [propertiesObject]) 建立一個新物件,包含兩個引數
proto, 新建立物件的原型物件
propertiesObject,可選。 包含一個或多個屬性描述符的 JavaScript 物件

let obj = Object.create(Object.prototype) //建立一個空對像
const YH = {
  sex: "woman",
  fun() {
    console.log(`我的名字是:${this.name}, 性別: ${this.sex}`);
  }
};

const LJJ = Object.create(YH); // 繼承YH的 sex 屬性 與 方法
LJJ.name = "劉家軍"; // name 是LJJ上的屬性 但不是YH上的
LJJ.sex = "man"; // 繼承的屬性可以被覆蓋
LJJ.fun();

物件分類

我們都知道 JavaScript中萬物皆物件,但物件之間也是有區別的。分為函式物件和普通物件。
函式物件可以建立普通物件,(這個我們上面講過了),回顧一下

function fun(){
    console.log("這是一個自定義建構函式")
};
let myFun= new fun();

普通物件沒法建立函式物件,凡是通過new Function建立的物件都是函式物件,其他都是普通物件(通常通過Object建立),可以通過typeof來判斷。

function fun1() {};
console.log(typeof fun1) // "function"

let obj1 = new fun1();
console.log(typeof obj1) // "object"
let obj2 = {};
console.log(typeof obj2) // "object"

關於函式的建立,注意以下寫法等價

function fun1() {}
等價於
let fun1 = new Function();

function fun2(a,b){
  console.log(a+b);
}
fun2(1,2)
等價於
let fun2= new Function('a','b',`console.log(a+b)`);
fun2(1,2)

簡單回顧一下
我們將物件分為函式物件普通物件,函式物件的級別要要高於普通物件,可以通過函式物件建立普通物件,但是無法通過普通物件建立函式物件
好了,進入正題!

什麼事js原型

每一個js物件(null除外)都和另一個物件相關聯,“另一個”物件就是原型,每一個物件都從原型繼承屬性
所有通過物件直接量建立的物件都具有同一個原型物件,可以通過Object.prototype獲取對原型物件的引用,注意以下程式碼

// dmeo1
const obj =new Object()
alert(obj.prototype) // undefined
alert(Object.prototype) // [object Object]
// demo2
function fun(){
    console.log("這是一個自定義建構函式")
};
alert(fun.prototype) // [object Object]

看以上程式碼,obj 為普通物件,obj的prototype為undefined,Object為js內建建構函式,Object存在prototype
我們得出以下結論
每一個函式物件都有一個prototype屬性,但是普通物件是沒有的;
換個方式再說一遍,只有函式物件才會存在prototype屬性,普通的物件不存在

還沒結束,看如下程式碼

function fun(){
    console.log("這是一個自定義建構函式")
};
console.log(fun.prototype)

輸出:

const obj = {}
console.log(obj.__proto__);

輸出:
在這裡插入圖片描述

const author='劉家軍'
console.log(author.__proto__);

輸出:
在這裡插入圖片描述

constructor

是建構函式建立的例項的屬性,該屬性的作用是指向建立當前物件的建構函式。(這個不是我們今天重點要介紹的)

_ _ proto_ _

這是什麼?根據我們的console.log,不難發現,函式物件,普通物件,都存在__proto__,這是什麼呢?__proto__和原型鏈有什麼聯絡呢?__proto__指向誰呢?
預知後事如何 且看明天分解