一日客語:中文:拜託你 客語:bai togˋnˇ 掰偷 三聲n
物件都有原型,當自己屬性找不到時就會往原型找,然後一直找一直找除非找到,要不就找到null
物件:物件的原型繼承某個“一般物件”: 使用方式 Object.setPrototypeOf
物件: 物件的來源是“建構函式”: 使用方式 new constructor
平常使用的物件方式
//像是雨傘學院,每人都有不同能力
const wendy = { fly: 30 };
const ann = { run: 50 };
const nick = { swimming: 100 };
console.log('fly' in wendy); //true
console.log('run' in wendy); //false
有個神奇想法
我想要ann的跑步能力!!!
把ann設為wendy的原型prototype
prototype可以在瀏覽器下看wendy物件[[prototype]],這裡觀察一下
要如何把ann變成我的原型?
使用Object.setPrototypeOf
(繼承者物件,原型物件)
Hint:使用in可以找屬性
方式:
1.wendy原型設ann:
Object.setPrototypeOf(wendy, ann);
console.log('run' in wendy); //true`
我想要得到誰力量就把那人設成我的原型
2.那ann原型設nick呢?ann就會得到nick的力量
3.然後wendy也會繼承ann和nick的屬性,這樣wendy會飛、跑、游泳
Object.setPrototypeOf(wendy, ann);
console.log('run' in wendy); //true
//把ann的原型設為nick,想要游泳能力
Object.setPrototypeOf(ann, nick);
//身為ann繼承者wendy也具有游泳的能力
console.log('swimming' in wendy);//true
Cat.prototype == nini.__proto__
最容易搞混的地方:
在瀏覽器觀察
建構函式有prototype屬性 =>Cat.prototype
nini(實例)有[[prototype]]屬性(但無法選取,只能靠其他方式) =>nini.__proto__
看到沒~就是這樣建立了不可告人的關係
還要注意建構子也有可能是別物件的實例
所以也會有prototype(會當某物件的爸)和[[prototype]](也可能是別人的兒子)
想法上:
Cat()
function Cat() { }
Cat.prototype.eat = function () {
return 'eat';
}
let b = Cat();//一般function
console.log(b); //undefined
但這樣只是呼叫function
根據剛剛說的 function 建出來的物件的原型也會是function prtototype
所以要思考如何才能讓function 建出物件? 使用new 運算子
new Cat()
此function會是 constructor (建構器)按照慣例要大寫
所以cat()=>Cat()
function Cat() {}
Cat.prototype.eat = function () {
return 'eat';
};
const a = new Cat();
console.log(a)//{}
console.log(a.eat());//eat
a是經由function 建立出的物件,這個物件的原型有eat方法
問題來了要如何在新物件上加上自帶屬性?? 可以使用this
”
mdn:
The new operator lets developers create an instance of a user-defined object type or of one of the built-in object types that has a constructor function
new運算子根據內建或自己定義的constructor function 創建instance(實例)
function Cat(name) {
this.name = name;
this.sleep = function () {
return 'sleeping';//這寫法不太好,晚點解釋
};
}
let cat1 = new Cat('kiki');
let cat2 = new Cat('niki');
let cat3 = new Cat('nini');
console.log('cat1', cat1);
//cat1 Cat { name: 'kiki', sleep: [Function (anonymous)] }
console.log('cat2', cat2);
//cat2 Cat { name: 'niki', sleep: [Function (anonymous)] }
console.log('cat3', cat3);
//cat3 Cat { name: 'nini', sleep: [Function (anonymous)] }
第三步:書上會說新的空物件會被設定為函式背景空間
this指的是新建立的物件
Cat()function 沒有回傳(return)物件會回傳新建立的物件
所以記憶體會撥出一塊空間放新物件
函式原型有constructor屬性會指向(reference)到原來的函式
重點筆記:
cat1 增加屬性可以三種方式
1.自帶自身的屬性:使用this
2.增加原型的屬性
3.增加實例的屬性
function Cat() {
this.name = 'kitty';
//自帶自身的屬性
this.sleep = function () {
//自帶自身的屬性
return 'sleeping';
};
}
let cat1 = new Cat();
Cat.prototype.fruit = 'apple'; //增加原型的屬性
cat1.lay = 'lay'; //增加實例屬性
console.log(cat1.fruit); //apple
console.log(cat1.sleep()); //sleeping
console.log(cat1.lay); //lay
Object.__proto__
Object.getPrototypeOf()
function Cat(name) {
this.name = name;
this.sleep = function () {
return 'sleeping';
};
}
let cat1 = new Cat('kiki');
Cat.prototype.eat = 'apple';
Cat.prototype.eyes = 2;
console.log(Object.getPrototypeOf(cat1));
//{ eat: 'apple', eyes: 2 }
console.log(cat1.__proto__);
//{ eat: 'apple', eyes: 2 }
console.log(cat1);
//Cat { name: 'kiki', sleep: [Function (anonymous)] }
Cat原型(prototype)的constructor屬性指向Function
function Cat(name) {
this.name = name;
this.sleep = function () {
return 'sleeping';
};
}
let cat1 = new Cat('kiki');
Cat.prototype.eat = 'apple';
Cat.prototype.eyes = 2;
console.log(Object.getPrototypeOf(cat1).constructor);
//[Function: Cat]
console.log(cat1.__proto__.constructor);
//[Function: Cat]
會先選擇instance(實例)優先於prototype(原型)
function Cat(name) {
this.name = name;
this.sleep = function () {
return 'sleeping';
};
this.eat = 'apple';//自身
}
Cat.prototype.eat = 'banana';//原型
Cat.prototype.eyes = 2;
let cat1 = new Cat('kiki');
console.log(cat1.eat); //apple
function Cat(name) {
this.name = name;
this.sleep = function () {
return 'sleeping';//這寫法不太好,晚點解釋
};
}
let cat1 = new Cat('kiki');
let cat2 = new Cat('niki');
let cat3 = new Cat('nini');
console.log('cat1', cat1);
//cat1 Cat { name: 'kiki', sleep: [Function (anonymous)] }
console.log('cat2', cat2);
//cat2 Cat { name: 'niki', sleep: [Function (anonymous)] }
console.log('cat3', cat3);
//cat3 Cat { name: 'nini', sleep: [Function (anonymous)] }
cat1、cat2、cat3都有各自sleep function,若當物件創立n個會有n個sleep function
在程式會希望相同邏輯會可以共用,儘可能省記憶體空間,因此加在Cat的原型下創建物件使用它的sleep function(只要一個)
原型我也還在學習,這是目前我理解的樣子
真是累的不要不要的QQ
(主要閱讀忍者開發技巧探秘第二版書籍)
資料來源:
忍者開發技巧探秘第二版
mdn