创建对象的方式
1、Object构造函数
var person = new Object(); person.name = "viven"; person.age = 28; person.sayAge = function(){ console.log(this.age); } person.sayAge()
2、对象字面量方式
var person ={ name: "viven", age: 28, sayAge:function(){ console.log(this.age); } } person.sayAge()
3、工厂模式 ----只能知道是Object的实例,不能判断是否是createPerson实例
function createPerson(name,age,job){ var o = new Object(); o.name = name; o.age = age; o.job = job; o.sayAge = function(){ console.log(this.age); }; return o; } var person1 = createPerson("viven",28,"didi"); var person2 = createPerson("kevin",26,"baidu"); console.log(person1.name); //viven person2.sayAge(); //26 console.log(person1 instanceof Object); //true console.log(person1 instanceof createPerson);//false
4、构造函数模式 ----person1,person2同时是Object的实例,因为所有的对象均继承Object
I.创建一个新对象
II.将构造函数的作用域赋值给对象(this指向)
III. 执行构造函数中的代码(添加属性)
IV.返回新对象
function Person(name,age,job){ this.name = name; this.age = age; this.job = job; this.sayAge =function(){ console.log(this.age); } } var person1 = new Person("viven",28,"didi"); var person2 = new Person("kevin",26,"baidu"); console.log(person1.name); //viven person2.sayAge(); //26 console.log(person1 instanceof Object); //true console.log(person2 instanceof Person); //true
把构造函数当做普通函数使用
//赋值给window Person("lal",22,"wangyi"); console.log(window.name);// lal
//在另一个对象的作用域中调用 var O = new Object(); Person.call(O,"bal",18,"tx"); O.sayAge(); //18
函数中每定义一个函数 就是实例化了一个对象。
function Person(name,age,job){ this.name = name; this.age = age; this.job = job; this.sayAge =function(){ console.log(this.age); } } var person1 = new Person("viven",28,"didi"); var person2 = new Person("kevin",26,"baidu"); console.log(person1.sayAge ==person2.sayAge); //false
那么我们可以将函数定义转移到构造函数之外。来解决这个问题
function Person(name,age,job){ this.name = name; this.age = age; this.job = job; this.sayAge = sayAge; } function sayAge(){ console.log(this.age); } var person1 = new Person("viven",28,"didi"); var person2 = new Person("kevin",26,"baidu"); console.log(person1.sayAge ==person2.sayAge);//true
这样一来,我们person1和person2就公用了在全局内的函数sayAge()。但是这样一来,在全局内定义函数,只能被实例化的Person来调用。怎么解决
5、原型模式
function Person(){ } Person.prototype.name = "viven"; Person.prototype.age = 26; Person.prototype.job = "wy"; Person.prototype.sayAge = function(){ console.log(this.age); } var person1 = new Person(); person1.age = 18; person1.sayAge() //18 var person2 = new Person(); person2.sayAge() //26
I.理解原型
每个原型对象会自动获得一个constructor属性。这个属性包含一个指向prototype的指针
Person.prototype.constructor 指向 Person
function Person(){ } Person.prototype.name = "viven"; Person.prototype.age = 26; Person.prototype.job = "wy"; Person.prototype.sayAge = function(){ console.log(this.age); } var person1 = new Person(); person1.age = 18; person1.sayAge() //18 来自实例化person1 var person2 = new Person(); person2.sayAge() //26 来自原型Person
为实例化的对象添加属性的时候会覆盖原型对象中的同名属性。可以删除通过delete
function Person(){ } Person.prototype.name = "viven"; Person.prototype.age = 26; Person.prototype.job = "wy"; Person.prototype.sayAge = function(){ console.log(this.age); } var person1 = new Person(); var person2 = new Person(); person1.age = 18; person1.sayAge() //18 来自实例化person1 person2.sayAge() //26 来自原型Person delete person1.age; person1.sayAge(); //26 来自原型Person
可以通过hasOwnProperty()方法检测访问的到底是实例属性还是原型属性。 返回true则是实例属性
function Person(){ } Person.prototype.name = "viven"; Person.prototype.age = 26; Person.prototype.job = "wy"; Person.prototype.sayAge = function(){ console.log(this.age); } var person1 = new Person(); var person2 = new Person(); person1.age = 18; person1.sayAge() //18 来自实例化person1 console.log(person1.hasOwnProperty("age")); //true person2.sayAge() //26 来自原型Person console.log(person2.hasOwnProperty("age")); //false delete person1.age; person1.sayAge(); //26 来自原型Person console.log(person1.hasOwnProperty("age")); //false
II.更简单的原型写法
function Person(){ } Person.prototype={ name: "viven", age: 26, job: "wy", sayAge: function(){ console.log(this.age); } }
这样的话,constructor就没有了。因为重新定义了原型prototype对象。如果需要的话可以这样
function Person(){ } Person.prototype={ constructor:Person, name: "viven", age: 26, job: "wy", sayAge: function(){ console.log(this.age); } }
定义一个constructor指向原来的Person构造函数。
III.原型对象的问题
忽略了构造函数中 传入参数的步骤,然后实例化的函数取得的值都是一样的。
6.组合使用构造函数和原型模式
function Person(name,age,job){ this.name = name; this.age = age; this.job = job; this.friends = ["shelby","count"]; } Person.prototype = { constructor: Person, sayAge: function(){ console.log(this.age); } } var person1 = new Person("viven",26,"wy"); var person2 = new Person("kevin",24,"al"); person1.friends.push("plmm"); console.log(person1.friends); console.log(person2.friends);
7、动态原型模式
function Person(name,age,job){ this.name = name; this.age = age; this.job = job; if(this.name != "function"){ Person.prototype.sayName = function(){ console.log(this.name); } } } var person1 = new Person("viven",26,"wy"); person1.sayName();
通过检查某个存在的方法是否有效来决定是否要初始化原型。
8、稳妥构造函数模式
function Person(name,age,job){ //创建要返回的对象 var o =new Object(); //定义私有变了和函数 o.haha = "smile"; //添加方法 o.sayName = function(){ console.log(name ); }; return o; } var person1 = Person("viven",26,"wy"); person1.sayName(); console.log(person1.name); //undefined
除了通过方法来访问里面的name值,没有其他方法来访问