普通對象和函數對象 // 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的原型對象。 原型鏈的訪問規則:先在自身的下面尋找,再去一級一級的往原型鏈上找。*/