首先來理解原型
原型 === 共用屬性
可以先看看方姐的幾篇文章:
什么是JS原型鏈
JS 中 proto 和 prototype 存在的意義是什么?
JS 的 new 到底是干什么的?
var obj = {}
obj.toString = ??? // 按常規(guī)邏輯來看,應該是undefined
//然而 打印結(jié)果是 "[object Object]"
//所以
obj.toString() = window.Object.prototype.toString()
這樣,就做到了代碼復用
再來看一個問題
var arr = [1,2,3]
arr.toString() = "1,2,3"
如果說每次調(diào)用toString()都相當于是調(diào)用window.Object.prototype那為什么不同的對象調(diào)用同一個toString()的時候打印出來的值不一樣呢?
是不是可以這樣假設:toString()知道是誰調(diào)用了它
實際上
obj.toString = obj.toString.call(obj);
obj被傳給toString()了
可以來證明一下
var arr = [1,2,3]
var arr2 = [4,5,6]
arr2.toString()
//打印出 "1,2,3" 這沒有問題
//那么
arr2.toString.call(arr)
"1,2,3"
//這樣就很明顯了
原型的用法?

按照上面的邏輯
obj.hi() === 共用屬性.hi.call(obj)
那么來改寫一下代碼
var 共用屬性 = {
hi(a){
console.log(a)
}
};
var obj = { name : "我是obj"};
obj.__proto__ = 共用屬性
obj.hi() // === 共用屬性.hi.call(obj)
能否打印出{ name : "我是obj"}?
結(jié)果卻是 undefined
???? 什么鬼????
這就要說到js的一個坑了,實際上obj確實傳給了共用屬性,但是 用別的形參無法獲取到,只能用this
相當于:
var 共用屬性 = {
hi(this,a){
console.log(a)
}
};
這里obj實際上是傳給了this,但是js默認隱藏了
所以把代碼改成:
var 共用屬性 = {
hi(){
console.log(this)
}
};
obj.hi();
{name : "我是obj"}
好,到這我們再來深入探究一下
obj.__proto__已經(jīng)等于了共用屬性,也就是說
obj.__proto__ != window.Object.prototype,那么obj.toString()會是undefined嗎?
答案是 no。
實際上,當你調(diào)用obj.toString()的時候,首先會在自身上看有沒有這個屬性,如果沒有,就會去你的原型上找,前面已經(jīng)設置了obj的原型等于共用屬性,所以,接著會在共用屬性上找有沒有toSring,還是沒有,然后會繼續(xù)去共用屬性的原型window.Object.prototype上找,找到了之后,調(diào)用window.Object.prototype.toString.call(obj)
當然,如果在window.Object.prototype上也沒有找到,會接著去它的原型上找....直到找到或者找到null為止
可以打印出來看看
window.Object.prototype.__proto__
null
所以,每當你聲明一個對象的時候,JS會默認給你執(zhí)行
新聲明的對象.__proto__=window.Object.prototype
或者
新聲明的對象.__proto__=window.Array.prototype
什么是類?
var obj1 = {
name : '張三',
age : 18
};
var obj2 = {
name : '李四',
age : 20
};
很明顯 obj1和obj2很相似,可以把它們歸為一類,所以可以把 obj1和obj2叫做同一類對象
那如果有不同的對象呢?
var obj3 = {
aaa = 1,
bbb = 2
};
明顯跟上面的不能算一類
如果同一類對象分為一類,那么我們怎么用代碼表示它呢?
方法有兩種:
- 寫一個文檔,在文檔中寫清楚
- 提供一個函數(shù)來創(chuàng)建這一類的對象
例
function createPerson(name='',age=18){
var obj = {}
obj.name = name
obj.age = age
return obj
};
//開始創(chuàng)建對象
createPerson()
{name : "",age:18}
createPerson("王二狗",16)
{name : "王二狗",age:16}
類是擁有共同特征的對象
再看上面的代碼,每個對象的name、age都不一樣,怎么在創(chuàng)建它們的時候給它們添加共有屬性呢?
當然是用原型
所以代碼可以改成
var 共有屬性 = {
attr1(){console.log("我們是同類")},
attr2: '同一類'
}
function createPerson(name='',age=18){
var obj = {}
obj.name = name
obj.age = age
obj.__proto__ = 共有屬性
return obj
};
開始創(chuàng)建對象

構(gòu)造函數(shù):創(chuàng)建某個類的對象的函數(shù)
類是擁有相同屬性的對象
自有屬性:對象自身的屬性
共有屬性:對象原型里的屬性
class
每一個class都有一個constructor(構(gòu)造函數(shù)),用來構(gòu)造自有屬性

那么共有屬性放在哪里呢?
很簡單,放在
constructor外面就可以了
目前 共有屬性只能是函數(shù)
再來看看復雜一點的
extends 繼承

注意:在要繼承的對象的構(gòu)造函數(shù)里一定要執(zhí)行super()
所以繼承extends的意思是:
如果一個類繼承了另一個類,那么這個類的對象就有被繼承的類的屬性
那么super()的作用是什么呢?
還是看代碼

p1居然具有了Animal的constructor里的屬性所以
super()的作用就是:執(zhí)行你繼承的類的constructor被繼承的類可以叫做 基類 或者 超類
所以
super()執(zhí)行一下超類的構(gòu)造函數(shù)super()必須放在constructor的第一行
再來看看 get
我們知道想要調(diào)用一個對象里的某個函數(shù),就得用對象名.函數(shù)名稱()這種方式,
如果在函數(shù)前面加一個get,就可以直接用對象名.函數(shù)的方法來調(diào)用了

但是有一個很嚴重的問題,如果前面寫錯了,后期除了更改源代碼以外,沒有辦法再修改
get函數(shù)里面的內(nèi)容
所以js又給了我們一個方法, set
具體用法如下

實際上
class是有些麻煩的 沒有原型靈活但是還是有一些優(yōu)點的,比如某個對象的一個屬性,我們想讓它是只讀的,不允許修改,就可以這樣

然后用
set來控制寫入
靜態(tài)方法 static
靜態(tài)方法就是只能通過類名.方法名來訪問的方法,new出來的對象都不能訪問
