js(ES5)面向物件
普通物件和函式物件
// var o1={};
// var o2=new Object();
// var o3=new f1();
// 凡是通過 new Function() 建立的物件都是函式物件,其他的都是普通物件,系統內建的函式物件Function,Object,Array,String,Number
// function f1() {
//
// }
// var f2=function () {
//
// }
// var f3=new Function("str","");
//
// console.log(typeof o1); //object
// console.log(typeof o2); //object
// console.log(typeof o3); //object
//
//
// console.log(typeof f1); //function
// console.log(typeof f2); //function
// console.log(typeof f3); //function
建構函式:
/*-------------------------建構函式constructor --------------------*/
function Person(name,age,job) {
this.name=name;
this.age=age;
this.job=job;
this.sayName=function () {
alert(this.name)
}
// 若忽略return則意味著返回this物件
console.log("++++++this",this) // Person{} 不寫new ,當成普通函式,指向widow
}
// person1 和 person2 都是 建構函式 Person 的例項 例項person1和 person2 的建構函式屬性(constructor)指向建構函式Person 。
// person1.constructor == Person
var person1=new Person("lichuyan",23,"web");
// .將建構函式中的Person的this指向物件person1。相對於普通函式,建構函式中的this是指向例項的,而普通函式呼叫中的this是指向windows的。
var person2=new Person("yuanmingqi",23,"java");
console.log("person1==person2",person1.sayName==person2.sayName) // false
// 缺點:可見這兩個物件並不是共用一個方法,每new一次,系統都會新建立一個記憶體,這兩個物件各自有各自的地盤,但他們具有相同的功能。還不共用,肯定不是我們所希望的。所以就有了下一種方法,原型+構造模式
原型物件
一:原型物件用處是繼承
原型物件是一個普通的物件,
// 定律1:每個物件都有 __proto(隱私原型)__ 屬性,但只有函式物件才有原型屬性也叫(prototype)原型物件,在這裡是Person.prototype;
// 所以我們只需要把想要共享的東西放在函式的prototype下,不想共享的東西通過建構函式來建立。
// 構造模式
function Person(name,age,job) {
this.name=name;
this.age=age;
this.job=job;
}
// 原型模式
Person.prototype.sayName=function () {
alert(this.name);
}
var person3=new Person("lichuyan",23,"web");
person3.sayName();
var person4=new Person("yuanmingqi",23,"java");
person4.sayName();
console.log("person3==person4",person3.sayName==person4.sayName) // true
// 測試為true,可見同一個函式造出來的例項物件能共享這個函式的prototype下的方法和屬性即showName()方法是共享的,也就是說他們共用一個記憶體,更進一步的說它們存在引用關係,也就是說你更改了p3的showName也會影響p4的showName
二:原型物件下可能有三種屬性
// 構造模式
function CreatePerson(name){
this.name = name;
}
// 原型模式
CreatePerson.prototype.showName = function(){
console.log(this.name);
};
var p1 =new CreatePerson('haha');
例項化物件怕p1通過_proto_屬性共享了原型物件的屬性和方法
p1.showName();
console.log("++++++++++例項p1",p1);
console.log("++++++++++例項p1的構造屬性",p1.constructor); // 指向建構函式
console.log("++++++++原型物件下的三個屬性",CreatePerson.prototype);
//1 原型物件所帶方法和屬性 2 constructor即CreatePerson()這個建構函式 3_proto_屬性
console.log("++++++++原型物件額構造屬性",CreatePerson.prototype.constructor);
console.log("++++++++是否一樣",p1.constructor===CreatePerson.prototype.constructor);
// 結論: 例項person1的建構函式屬性(constructor)指向建構函式CreatePerson=
// 原型物件的建構函式屬性指向建構函式CreatePerson
// 1:在預設情況下,所有的原型物件都會自動獲得一個 constructor(建構函式)屬性,這個屬性(是一個指標)指向函式(Person)既Person.prototype.constructor == Person
// 定律2:原型物件(Person.prototype)也是 建構函式(Person)的一個例項。
圖
_proto_屬性:
/* _proto_屬性:
同一個函式造出來的例項物件能共享這個函式的prototype下的方法和屬性,但是它是如何做到的呢?這裡要出場的就是_proto_屬性.
每個例項化物件都有_proto_屬性,它是一個指標,指向函式的prototype,也就是儲存了它的地址。
(JS中任何物件的值都是儲存在堆記憶體中,我們宣告的變數只是一個指標,儲存了這個物件的實際地址,所以有了地址就能找到物件),
所以總得來說,每個例項化物件都有_proto_屬性,儲存了建構函式的原型物件的地址,通過這個屬性就可以擁有原型物件下的所有屬性和方法,_proto_屬性實際就是例項化物件和原型物件之間的連線
*/
原型鏈:
/*
每個函式都可以成為建構函式,每個函式都有原型物件,每個原型物件也可以是一個例項化物件,比如,你建立了一個函式fun,
它是建構函式function的例項化物件,而function的原型物件,又是Object的例項物件。所以fun有個_proto_屬性可以訪問到function的原型物件,function原型物件也是個例項物件,也有個_proto_屬性,可以訪問到Object的原型物件,所以通過_proto_屬性,就形成了一條原型鏈。每個例項化物件都可以訪問到鏈子上方的方法和屬性
,所以fun是可以訪問Object原型物件下的方法和屬性的。實際上所有物件都可以訪問到Object的原型物件。
原型鏈的訪問規則:先在自身的下面尋找,再去一級一級的往原型鏈上找。*/