js中的原型對象,原型鏈(入門級別)

當我寫完博客標題的時候就有點小後悔了,這個標題好像有點大了,單單一個原型對象其實就可以扯很多了,有一個函數庫 叫做 prototype.js 就是對原型對象的各種封裝吧 但我僅僅也就是了解。
我以前面試過的幾家公司也問過原型和作用域的問題,畢竟傳統的js 實現面向對象很重要的一點就是靠原型對象來實現了,之前就一直想寫一些關於這方面的東西,期間也因爲其他的事情耽誤了,今天就來聊一聊 菜鳥對這個的理解吧
1.原型對象
相信不瞭解的原型對象的小夥伴 也一定會見過 prototype 這個關鍵字吧,要說原型對象那麼就和構造函數扯不開關係了,因爲在構造函數誕生的時候 就有一個原型對象相伴而生

// 下面的Person 就是一個 構造函數
// 其實構造函數也沒有那麼多深層意義 就是完成 一個類實例化的一些初始化操作 
// Person 就可以看做是一個類   一般類名要大寫的哦
function Person(name,age){
	this.name=name;
	this.age=age;
}
var person=new Person("zhangsan",18);// person 是Person 的一個實例化對象
console.log(person.name,person.age); // 輸出  zhangsan age

然後我們順着構造函數這條線索去找他的原型對象
上面所說的 prototype 就是指向 他的原型對象 我們 嘗試着看一看長啥樣哈

console.log(Person.prototype);
// 下面的就是打印的東西了
constructor: ƒ}constructor: ƒ Person(name,age)__proto__: Object

我們可以看到哈 原型對象 裏面 有一個構造函數 constructor :Person 指向了它本身
後面還有一個__proto__ 這個東西 我們一會在講解
上面看到了 原型對象中 有一個 constructor的屬性 屬性值 是一個和我們的構造函數同名的函數
那他倆是一個東西嗎 我們在嘗試打印試試看看

console.log(Person.prototype.constructor===Person); // true

看來我們猜測的是對的 就是指向了我們定義的構造函數
這裏注意哈 原型對象就是 比較特殊的 普通對象 {} 只是裏面有些系統給我們定義好的屬性罷了
不要把它想的太複雜哈 也不要把它當做js中的一個新知識來學 都是js中基礎慢慢加強封裝得到的 所以說基礎還是很重要的 是你是否能完成高樓大廈的根本要素

那既然是一個對象 那我們給她添加點屬性 應該可以吧

Person.prototype.sex="男"; // 我給原型對象加了一個 sex的屬性 屬性值是 男

直接使用 Person.prototype.sex 肯定是能訪問到了
但是 我不用他來訪問了 上面不是還一直有一個 實例化對象嗎 我用它來訪問
// 我把上面的代碼 再克隆一份

function Person(name,age){
	this.name=name;
	this.age=age;
}
var person=new Person("zhangsan",18);
console.log(person.sex); // undefined
Person.prototype.sex="男"
console.log(person.sex); //  男

這個就很奇怪是把 爲啥上面輸出undefined 下面的是 男
很關鍵的一點就是 我們給Person 類的原型原型對象 加上一個 sex的屬性之後 他就訪問到了
上面 我曾經說過的 一個 proto 說之後再將 這裏 我們嘗試下 打印下 person 實例化的對象他的 proto 看看長啥樣子

console.log(person.__proto__);
// 下面的打印出來了 這個
{sex: "男", constructor: ƒ}
sex
:
"男"
constructor
:
ƒ Person(name,age)
__proto__
:
Object

我們看到了 sex 那個屬性 這個是 Person 實例化對象的 proto_ 看起來好像我們Person類的原型對象是把
我們再去打印下 我們 構造函數的原型對象看看 是不是也長這樣

console.log(Person.prototype);
{sex: "男", constructor: ƒ}
sex
:
"男"
constructor
:
ƒ Person(name,age)
__proto__
:
Object

好神奇啊 他兩一模一樣 不是嗎 這裏 我們就要論證 他們兩 是不是相等了

console.log(Person.prototype===person.__proto__); // true

果不其然 他兩 全等情況下 打印的是 true 那就是說兩者指向的地方是相同的 
根據上面我們得到一個結論哈: 構造函數的原型對象和實例化出來子類的 proto 是相同的,
當然返貨來說也行 子類的__proto__指向父類的的原型對象
不過這裏還有一個疑問就是  上面的 person 對象並沒有 sex 那個屬性 他怎麼打印出來了呢
這裏附帶一個注意事項: 一般不要直接覆蓋掉構造函數的原型對象哈 這樣很危險

Person.prototype={};
console.log(Person.prototype.constructor==Person); // 輸出 false

這裏終於牽扯出來了 另一個主題 就是原型鏈的問題
我們再把上面的代碼拿過來 看看

function Person(name,age){
	this.name=name;
	this.age=age;
}
var person=new Person("zhangsan",18);
console.log(person.sex); // undefined
Person.prototype.sex="男"
console.log(person.sex); //  男

根據上面的總結來說 就是 父類的實例化對象 就是例子中的 person
打印出來的屬性 sex 它本身是沒有 這個屬性 但是他的父親的原型對象中有
他就會沿着 proto 去找到他的父親 原型對象 然後打印出來這個 屬性值 如果他的父親也沒有 那麼他就會接着往上走 根據父親的 proto
我們在上面不是看到 Person 構造函數 也確實有 __proto__的存在
爲了滿足大家的好奇心哈 我也打印下 Person的 proto

console.log(Person.prototype.__proto__)

他給我打印了下面的一大串 不過看見了一個核心的東西了 constructor
在這裏插入圖片描述
不就是我們的 標準數據類型之一的 Object 嗎 爲了驗證我們的猜想哈

console.log(Person.prototype.__proto__.constructor==Object); // true

真的耶 打印出來了 true 這個說明了 Person的父親是 Object
這樣也能明白 爲啥 說 OBject 是一切對向的祖先了 這裏再附上一個小知識就是
null 是一切對象的 源頭 因爲源頭就是空嘛 哈哈 起源
最後可能懵懵懂懂知道了 原型對象和原型鏈的概念了,
原型鏈: 由於逐級繼承產生了一條再各個對象之間通過原型對象實現的鏈條,本對象找不讀到的屬性和方法可以沿着這個鏈條 往上走 直到找到爲止,找不到 就輸出 undefined

還有朋友 想看看 作用域和作用域鏈條 關注我 後面持續更新

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