原型prototype
-
- 原型的定義
-
-
-
- 注意
-
-
- 原型的用途
- 原型的特點
- 原型鍊
-
-
- Function函數
- Object函數
- 函數對象關系
- 原型鍊機制
-
原型的定義
- 在JavaScript中,任何一個函數,都有一個prototype屬性,指向一個對象。
- 輸出了一個函數的prototype屬性,你會發現是一個空對象。輸出這個prototype的類型,發現是object類型
- prototype就是英語“原型”的意思。每個函數都有原型,原型是一個對象
function fun(){
alert("Hi");
}
console.log(fun.prototype); // Object{}
console.log(typeof fun.prototype); // Object
// 構造函數,構造函數裡面沒有任何語句,也就是說,
// 這個構造函數在執行的時候,不會給建立出來的對象添加任何屬性。
function Person() {
}
// 構造函數的原型,我們更改了構造函數的原型,為一個新的對象:
Person.prototype = {
name: "蔡徐坤",
sex: "男",
age: 18
}
// 當一個對象被new出來的時候,不僅僅執行了構造函數裡面的語句,
// 也會把這個函數__proto__指向構造函數的Person。
let obj= new Person();
console.log(obj.__proto__); // {name: "蔡徐坤", sex: "男", age: 18}
console.log(obj.__proto__ == Person.prototype); // true
//當我們試圖通路name、sex、age屬性的時候,身上沒有
// 那麼就去查找原型,原型身有,就當做了自己的屬性傳回了
console.log(obj.name); // 蔡徐坤
console.log(obj.sex); // 男
console.log(obj.age); // 18
prototype一定是函數的屬性!當這個函數是一個構造函數的時候,那麼它new出來的對象,将以它的原型那個對象為new出來的執行個體的原型對象
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsICM38FdsYkRGZkRG9lcvx2bjxiNx8VZ6l2cs0TPB1keRpXT4NGROBDOsJGcohVYsR2MMBjVtJWd0ckW65UbM5WOHJWa5kHT20ESjBjUIF2X0hXZ0xCMx81dvRWYoNHLrdEZwZ1Rh5WNXp1bwNjW1ZUba9VZwlHdssmch1mclRXY39CXldWYtlWPzNXZj9mcw1ycz9WL49zZwpmLykjNzMDOyIjM5ETOwkTMwIzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.jpg)
注意
任何一個對象,都有__proto__屬性,這個屬性指向自己的原型對象
原型的用途
定義一個方法的時候,如果寫在構造函數裡面:
function Person(name, age) {
this.name = name;
this.age = age;
this.say = function () {
console.log("你好,我是" + this.name + "我今年" + this.age + "歲了");
}
}
let obj1 = new Person("菜虛鲲", 12);
let obj2 = new Person("踩墟捆", 11);
obj1.say(); // 你好,我是菜虛鲲我今年12歲了
obj2.say(); // 你好,我是踩墟捆我今年11歲了
實際上,這個函數被複制了兩份,一份給了obj1,一份給了obj2, obj1和obj2這兩個執行個體身上有了相同功能的函數,但是這個函數不是同一個函數
那該如何解決這個問題呢, 一句話:所有的屬性要綁在對象身上,而所有的方法定義在對象的原型對象中:
function Person(name, age) {
// 構造函數裡面,負責定義一些屬性,随着構造函數的執行,這些屬性将綁定到new出來的對象身上
this.name = name;
this.age = age;
}
// 把所有的方法,定義在原型對象身上:
Person.prototype.say = function () {
console.log("你好,我是" + this.name + "我今年" + this.age + "歲了");
}
let obj1 = new Person("菜虛鲲", 12);
let obj2 = new Person("踩墟捆", 11);
obj1.say(); // 你好,我是菜虛鲲我今年12歲了
obj2.say(); // 你好,我是踩墟捆我今年11歲了
證明了obj1的say方法和obj1的say方法,是同一個函數 , 記憶體消耗小很多
原型的特點
- 存儲在prototype中的方法可以被對應構造函數建立出來的所有對象共享
- prototype中除了可以存儲方法以外, 還可以存儲屬性
- prototype如果出現了和構造函數中同名的屬性或者方法, 對象在通路的時候, 通路到的是構造函中的資料
function Person(name, age) {
this.name = name;
this.age = age;
this.currentType = "構造函數中的type";
this.say = function () {
console.log("構造函數中的say");
}
}
Person.prototype = {
currentType: "人",
say: function () {
console.log("hello world");
}
}
let obj1 = new Person("菜虛鲲", 34);
obj1.say(); // 構造函數中的say
console.log(obj1.currentType); // 構造函數中的type
let obj2 = new Person("踩墟捆", 44);
obj2.say(); // 構造函數中的say
console.log(obj2.currentType); // 構造函數中的type
- 在給一個對象不存在的屬性設定值的時候, 不會去原型對象中查找, 如果目前對象沒有就會給目前對象新增一個不存在的屬性
function Person(name, age) {
this.name = name;
this.age = age;
}
Person.prototype = {
constructor: Person,
currentType: "人",
say: function () {
console.log("hi");
}
}
let obj = new Person("蔡徐坤", 12);
obj.currentType = "新設定的值";
console.log(obj.currentType); // 新設定的值
console.log(obj.__proto__.currentType); // "人"
原型鍊
Function函數
- JavaScript中函數是引用類型(對象類型), 既然是對象, 是以也是通過構造函數建立出來的, "所有函數"都是通過Function構造函數建立出來的對象
- JavaScript中隻要是"函數"就有prototype屬性
- Function函數"的prototype屬性指向"Function原型對象"
- JavaScript中隻要是"原型對象"就有constructor屬性
- "Function原型對象"的constructor指向它對應的構造函數
- Person構造函數是Function構造函數的執行個體對象, 是以也有__proto__屬性
- Person構造函數的__proto__屬性指向"Function原型對象"
JS-原型鍊
function Person(name, age) {
this.name = name;
this.age = age;
}
let obj1 = new Person('踩墟捆', 12);
console.log(Function); // ƒ Function() { [native code] }
console.log(Function.prototype); // ƒ () { [native code] }
console.log(Function.prototype.constructor); // ƒ Function() { [native code] }
console.log(Function === Function.prototype.constructor); // true
console.log(Person.__proto__); // ƒ () { [native code] }
console.log(Person.__proto__ === Function.prototype); // true
Object函數
-
Object是一個函數,是系統内置的構造函數,用于創造對象的 , Object.prototype是所有對象的原型鍊終點
是以,當我們在一個對象上打點調用某個方法的時候,系統會沿着原型鍊去尋找它的定義,一直找到Object.prototype
function Person(name, age) {
this.name = name;
this.age = age;
}
let obj1 = new Person('踩墟捆', 19);
console.log(Function.__proto__); // ƒ () { [native code] }
console.log(Function.__proto__ === Function.prototype); // true
console.log(Object); // ƒ Object() { [native code] }
console.log(Object.__proto__); // ƒ () { [native code] }
console.log(Object.__proto__ === Function.prototype); // true
console.log(Object.prototype); // {constructor: ƒ,
__defineGetter__: ƒ, __defineSetter__: ƒ, hasOwnProperty: ƒ,
__lookupGetter__: ƒ, …}
console.log(Object.prototype.constructor); // ƒ Object() { [native code] }
console.log(Object.prototype.constructor === Object); // true
console.log(Object.prototype.__proto__); // null
函數對象關系
- 所有的構造函數都有一個prototype屬性, 所有prototype屬性都指向自己的原型對象
- 所有的原型對象都有一個constructor屬性, 所有constructor屬性都指向自己的構造函數
- 所有函數都是Function構造函數的執行個體對象(Function函數是所有函數的祖先函數)
- 所有函數都是對象, 包括Function構造函數
- 所有對象都有__proto__屬性
- 普通對象的__proto__屬性指向建立它的那個構造函數對應的"原型對象"
- 所有對象的__proto__屬性最終都會指向"Object原型對象"
- "Object原型對象"的__proto__屬性指向NULL
JS-原型鍊
function Person(name, age) {
this.name = name;
this.age = age;
}
let obj1 = new Person('踩墟捆', 12);
console.log(Function.prototype.__proto__); // Object
console.log(Person.prototype.__proto__); // Object
console.log(Function.prototype.__proto__ === Person.prototype.__proto__); // true
console.log(Function.prototype.__proto__ === Object.prototype); //true
console.log(Person.prototype.__proto__ === Object.prototype); // true
原型鍊機制
- 對象中__proto__組成的鍊條我們稱之為原型鍊
- 對象在查找屬性和方法的時候, 會先在目前對象查找
- 如果目前對象中找不到想要的, 會依次去上一級原型對象中查找 , 如果找到Object原型對象都沒有找到, 就會報錯
function Person(name, age) {
this.name = name;
this.age = age;
this.currentType = "構造函數中的type";
}
Person.prototype = {
// 注意點: 為了不破壞原有的關系, 在給prototype指派的時候
// 需要在自定義的對象中手動的添加constructor屬性, 手動的指定需要指向誰
constructor: Person,
// 構造函數中的屬性或方法會替換原型對象中的屬性或方法
currentType: "人",
say: function () {
console.log("Hi");
}
}
let obj1 = new Person("lnj", 34);
console.log(obj1.currentType); // 構造函數中的type
console.log(Person.prototype.constructor); // ƒ Person(name, age) {...}