创建对象的方式

1.工厂模式

function person(name,age){
var o = new Object();
o.name = name;
o.age = age;
o.sayName = function(){
console.log(this.name);
}
return o;
}
var p1 = new person('mi',18);
var p2 = new person('ni',19);
p1.sayName();
p2.sayName();
console.log(p1 instanceof Object);
console.log(p1 instanceof person);  //false
 
2.构造函数模式
function Person1(name,age){
// var this = new Object();
this.name = name;
this.age = age;
this.sayName = function(){
console.log(this.name)
}
}
var p3 = new Person1('g1',20);
var p4 = new Person1('g2',21);
p3.sayName();
p4.sayName();
console.log(p3 instanceof Object);
console.log(p3 instanceof Person1);  //true
构造函数所创建的实例指向 Object   又指向  Person1
 
//3.把函数定义放在函数外边
console.log('把函数定义放在函数外边')
function Person3(name,age,job){
this.name = name;
this.age = age;
this.sayName = sayName();
}
function sayName(){
console.log(this.name);
}
var p3 = new Person1('g3',30);
var p4 = new Person1('g4',31);
p3.sayName();
p4.sayName();
console.log(p3.sayName === p4.sayName);

//这种方式的缺点 ,全局作用域的方法只能被某个对象调用,如果需要定义很多方法,就会定义很多全局函数,这样就没有了封装性。由此引出了原型模式
//4.原型模式
console.log('原型模式');
function Person4(){
 
}
Person4.prototype.name = 'yx';
Person4.prototype.age = 18;
Person4.prototype.sayName = function(){
console.log(this.name);
}
// Person4.sayName = new Function("console.log(this.name)");
var p5 = new Person4();
var p6 = new Person4();
p5.sayName();
p6.sayName();
console.log(p5.hasOwnProperty('name'));

console.log('实例中创建值');
p5.name = 'gb'; //将会屏蔽掉原型中的值,只执行一次搜索
p5.sayName(); //来自实例

delete p5.name;
console.log('delete实例属性后');
p5.sayName();
console.log(p5.hasOwnProperty('name'));
p6.sayName(); //来自原型
console.log(Person4.prototype.isPrototypeOf(p5));
console.log(Object.getPrototypeOf(p5));
 

//原型模式引申出得原型链, 以及 isPrototypeOf(), Object.getPrototypeOf()
//1.工厂模式
console.log('工厂模式');
 
function person(name,age){
var o = new Object();
o.name = name;
o.age = age;
o.sayName = function(){
console.log(this.name);
}
return o;
}
var p1 = new person('mi',18);
var p2 = new person('ni',19);
p1.sayName();
p2.sayName();
console.log(p1 instanceof Object);
console.log(p1 instanceof person);
console.log(person instanceof Object);
console.log(p1.sayName === p2.sayName);


//构造函数模式
//构造函数创建对象的时候有四个步骤
console.log('构造函数模式');
function Person1(name,age){
// var this = new Object();
this.name = name;
this.age = age;
// this.sayName = function(){
// console.log(this.name)
// }
this.sayName = new Function("console.log(this.name)"); //与声明函数在逻辑上是等价的 会导致不同的作用域链和标识符解析
}
var p3 = new Person1('g1',20);
var p4 = new Person1('g2',21);
p3.sayName();
p4.sayName();
console.log(p3 instanceof Object);
console.log(p3 instanceof Person1);
console.log(Person1 instanceof Object);


//构造函数的缺点
console.log(p3.sayName === p4.sayName); //false 因为在ECMA中函数就是对象,每定义一个对象就创建了一个实例
//等价于 this.name = new Function("console.log(this.name)"")
//创建两个同等作用的函数没必要 可以把函数定义放在构造函数外部

//3.把函数定义放在函数外边
console.log('把函数定义放在函数外边')
function Person3(name,age,job){
this.name = name;
this.age = age;
this.sayName = sayName();
}
function sayName(){
console.log(this.name);
}
var p3 = new Person1('g3',30);
var p4 = new Person1('g4',31);
p3.sayName();
p4.sayName();
console.log(p3.sayName === p4.sayName);

//这种方式的缺点 ,全局作用域的方法只能被某个对象调用,如果需要定义很多方法,就会定义很多全局函数,这样就没有了封装性。由此引出了原型模式

//4.原型模式
console.log('原型模式');
function Person4(){
 
}
Person4.prototype.name = 'yx';
Person4.prototype.age = 18;
Person4.prototype.sayName = function(){
console.log(this.name);
}
// Person4.sayName = new Function("console.log(this.name)");
var p5 = new Person4();
var p6 = new Person4();
p5.sayName();
p6.sayName();
console.log(p5.hasOwnProperty('name'));

console.log('实例中创建值');
p5.name = 'gb'; //将会屏蔽掉原型中的值,只执行一次搜索
p5.sayName(); //来自实例

delete p5.name;
console.log('delete实例属性后');
p5.sayName();
console.log(p5.hasOwnProperty('name'));
p6.sayName(); //来自原型
console.log(Person4.prototype.isPrototypeOf(p5));
console.log(Object.getPrototypeOf(p5));
 

//原型模式引申出得原型链, 以及 isPrototypeOf(), Object.getPrototypeOf()
posted @ 2019-04-14 17:21  涂涂前端  阅读(109)  评论(0编辑  收藏  举报