js(ES5)面向對象以及原理
阿新 • • 發佈:2019-01-15
模式 進一步 函數調用 屬性和方法 color als 內置 pro +++
普通對象和函數對象 // 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的原型對象。 原型鏈的訪問規則:先在自身的下面尋找,再去一級一級的往原型鏈上找。*/
js(ES5)面向對象以及原理