1,面向對象
JS(ES5)本身是沒有class類型的,但是每個函數都有一個prototype屬性。JavaScript並不是通過類而是通過構造函數來創建對象的。prototype指向一個對象,當函數作爲構造函數時,prototype起到類似class的作用。
function Person(name) {
this.name = name;
this.sayHello = function () {
console.log("Hello, " + this.name)
}
}
var zhangsan = new Person("張三");
zhangsan.sayHello(); // Hello, 張三
var lisi = new Person("李四");
lisi.sayHello(); // Hello, 李四
每創建一個Person構造函數,都會爲該對象創建一個sayHello方法。實例化1000個Person對象,就會創建1000個sayHello方法,而這1000個sayHello方法是一模一樣的。那爲什麼不把這個方法單獨放置到一個地方,讓所有實例化對象都能訪問到呢。這就需要原型了。
2,原型
我們創建的每一個函數都有一個prototype屬性,這個屬性是指向原型對象的指針,原型對象包含着所有實例所共享的屬性和方法。每個對象實例都會在其內部初始化一個__proto__屬性,它是一個指向prototype(原型對象)的指針。原型對象中有一個屬性constructor又指向函數對象。
function Person(name) {
this.name = name;
}
Person.prototype.age = 18;
Person.prototype.sayHello = function () {
console.log("Hello, My name is " + this.name + ", " + this.age + " years old");
}
var xiongda = new Person("熊大");
xiongda.sayHello(); // Hello, My name is 熊大, 18 years old
--xiongda.__proto__.age;
var xionger = new Person("熊二"); // Hello, My name is 熊二, 17 years old
xionger.sayHello();
console.log(xiongda.__proto__ == Person.prototype) // true
console.log(xionger.__proto__ == Person.prototype) // true
console.log(Person == Person.prototype.constructor) // true
3,原型鏈
當我們訪問一個對象的屬性時,如果這個對象內部不存在這個屬性那麼他們就會通過__proto__屬性去prototype裏找這個屬性,這個prototype又會有自己的__proto__指向自己的原型對象,於是就這樣一直找下去,形成原型鏈的概念。 原型鏈實現的是對屬性的查找,一直順着原型鏈查找到Object對象,如果沒有查找到就會返回undefined。 如果改變某個原型時,與它相關的對象也會繼承這一改變。
4,參考文章
4.1 原型與原型鏈詳解
https://www.jianshu.com/p/ddaa5179cda6
4.2 JS-原型及其作用
https://segmentfault.com/a/1190000014466479?utm_source=channel-hottest