普通对象和函数对象 // 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的原型对象。 原型链的访问规则:先在自身的下面寻找,再去一级一级的往原型链上找。*/