筆記說明
重學前端是程劭非(winter)【前手機淘寶前端負責人】在極客時間開的一個專欄,每天10分鐘,重構你的前端知識體系,筆者主要整理學習過程的一些要點筆記以及感悟,完整的可以加入winter的專欄學習【原文有winter的語音】,如有侵權請聯系我,郵箱:kaimo313@foxmail.com。
一、什么是原型?
1.0、定義
原型是指一個詞語或一個類型意義的所有典型模型或原形象,是一個類型的組典型特征
1.1、基于類的編程語言
諸如 C++、Java 等流行的編程語言是使用類的方式來描述對象,
基于類
的編程提倡使用一個關注分類和類之間關系開發模型。
1.2、基于原型的編程語言
如 JavaScript 編程語言是利用原型來描述對象,
基于原型
的編程看起來更為提倡程序員去關注一系列對象實例的行為,而后才去關心如何將這些對象,劃分到最近的使用方式相似的原型對象,而不是將它們分成類。
1.3、原型系統的“復制操作”有兩種實現思路
- 一個是并不真的去復制一個原型對象,而是使得新對象持有一個原型的引用
- 另一個是切實地復制對象,從此兩個對象再無關聯。
javaScript選擇了第一種方式。
二、JavaScript 的原型
2.0、原型系統的兩條概括
- 如果所有對象都有私有字段
[[prototype]]
,就是對象的原型 - 讀一個屬性,如果對象本身沒有,則會繼續訪問對象的原型,直到原型為空或者找到為止。
2.1、三個內置函數
可以利用下面三個方法,更直接地訪問操縱原型,來實現抽象和復用。
Object.create
根據指定的原型創建新對象,原型可以是null
Object.getPrototypeOf
獲得一個對象的原型Object.setPrototypeOf
設置一個對象的原型
winter舉了用原型來抽象貓和虎的例子:
var cat = {say() {console.log("meow~");},jump() {console.log("jump");}
}var tiger = Object.create(cat, {say: {writable: true,configurable: true,enumerable: true,value: function(){console.log("roar!");}}
})var anotherCat = Object.create(cat);anotherCat.say(); // meow~var anotherTiger = Object.create(tiger);anotherTiger.say(); // roar!復制代碼
三、早期版本中的類與原型
3.0、“類”的定義是一個私有屬性 [[class]]
所有具有內置 class 屬性的對象:(ES3和之前版本)
var o = new Object;
var n = new Number;
var s = new String;
var b = new Boolean;
var d = new Date;
var arg = function(){ return arguments }();
var r = new RegExp;
var f = new Function;
var arr = new Array;
var e = new Error;
console.log([o, n, s, b, d, arg, r, f, arr, e].map(v => Object.prototype.toString.call(v))
)復制代碼
語言使用者唯一可以訪問 [[class]] 屬性的方式是 Object.prototype.toString
。
3.1、[[class]]
私有屬性被 Symbol.toStringTag
代替
可以查看MDN文檔Symbol.toStringTag以及Object.prototype.toString的介紹:(ES5開始)
var o = { [Symbol.toStringTag]: "MyObject" }
console.log(o + ""); // [object MyObject]
復制代碼
上面這段代碼創建了一個新對象,并且給它唯一的一個屬性 Symbol.toStringTag
,用字符串加法觸發了Object.prototype.toString
的調用,發現這個屬性最終對 Object.prototype.toString
的結果產生了影響。
3.2、new運算做了什么?
- 1、以構造器的
prototype
屬性(注意與私有字段[[prototype]]
的區分)為原型,創建新對象 - 2、將
this
和調用參數傳給構造器,執行 - 3、如果構造器返回的是對象,則返回,否則返回第一步創建的對象。
用構造器模擬類的兩種方法:
// 1、在構造器中修改 this,給 this 添加屬性function c1() {this.p1 = 1;this.p2 = function(){console.log(this.p1);}
}
var o1 = new c1;
o1.p2(); // 1// 2、修改構造器的 prototype 屬性指向的對象,它是從這個構造器構造出來的所有對象的原型。function c2() {
}
c2.prototype.p1 = 1;
c2.prototype.p2 = function() {console.log(this.p1);
}var o2 = new c2;
o2.p2(); // 1復制代碼
四、ES6 中的類
4.0、類的基本寫法
class Rectangle {constructor(height, width) {this.height = height;this.width = width;}// Getterget area() {return this.calcArea();}// MethodcalcArea() {return this.height * this.width;}
}復制代碼
4.1、類的繼承能力
class Animal {constructor(name) {this.name = name;}speak() {console.log(this.name + ' makes a noise.');}
}class Dog extends Animal {constructor(name) {super(name); // call the super class constructor and pass in the name parameter}speak() {console.log(this.name + ' barks.');}
}let d = new Dog('Mitzie');
d.speak(); // Mitzie barks.復制代碼
上面代碼調用子類的 speak 方法獲取了父類的 name。如果對于class
還想了解更多,可以查看MDN文檔Classes部分。
個人總結
其實對于這一部分很是不明白,也不清楚,對于這些js基礎性的東西還是要多下下功夫才行,畢竟winter的重學前端真心不錯,對我來說進行查漏補缺,看清自己的水平很有幫助,路還很長,還要加油呀!!!