JavaScript:创建对象(原型模式和构造函数模式)

JavaScript:对象

一、理解对象

var person = {}

Object.defineProperty(person,'name',{

  writable:false,

  value : 'Nike'

})

console.log(person.name);

person.name = 'Gray';

console.log(person.name);

console.log(person);

二、创建对象

2.1、工厂模式

function Person(name,age,job){

  var obj = new Object()

      obj.name = name

      obj.age = age

      obj.job = job

      obj.sayName = function(){

       console.log(this.name);

      }

       return obj;

}

var person = Person('Loly',13,'程序员');

person.sayName() //Loly

2.2、构造函数模式

function Person(name,age,job) {

      this.name = name;

      this.age = age;

      this.job = job;

      this.sayName = function(){

       console.log(this.name);

      }
}

创建Person的新实例,必须使用new操作符

1、创建一个新对象

2、将构造函数的作用域赋给新对象

3、执行构造函数中的代码

4、返回新对象

var person = new Person('Ahad',23,'sad')

person.sayName()

console.log(person.constructor == Person);//true

console.log(person instanceof Object);//true

console.log(person instanceof Person);//true

2.3、原型模式

function Person(){
    
}

Person.prototype.name = "Mike";

Person.prototype.age = 12;

Person.prototype.sayName = function(){

  	console.log(this.name);

}

var person = new Person();

var otherperson = new Person();

console.log(person.sayName == otherperson.sayName)//true  属性和方法是绑定在原型上的,是可共享的


//getPrototypeOf返回的对象是这个对象的原型

Object.getPrototypeOf(person);//Person


//isPrototypeOf()方法:确定对象之间是否存在原型和实例关系

Person.prototype.isPrototypeOf(person);//true


//hasOwnProperty():检测一个属性是否存在于实例中

person.name = 'Gery'

console.log(person.hasOwnProperty('name'));//true   此时name来自实例

delete person.name

console.log(person.hasOwnProperty('name'));//false   此时name来自原型,实例没有属于自己的name属性
//原型与in操作符( 无论该属性存在于实例还是原型 )

console.log('name' in person);//true    name来自原型

person.name = 'Gery'

console.log('name' in person);//true    name来自实例

//hasOwnProperty和in操作符合作判断属性是原型的还是实例对象的

function hasPrototypeProperty(object,name){

  return !object.hasOwnProperty(name) && (name in object);

}
function Per(){}

Per.prototype.name = 'Mike'

var per = new Per();

console.log(hasPrototypeProperty(per,'name'));
//true  per.hasOwnProperty(name)是0,取反为1,1&&1=1,name属于原型

per.name = 'Dike'

console.log(hasPrototypeProperty(per,'name'));
//false  per.hasOwnProperty(name)是1,取反为0,1&&0=0,name属于实例
//Object.keys()返回一个包含所有可枚举属性的字符串数组

Object.keys(Person.prototype);		//['name', 'age', 'sayName']

Object.keys(person);			    //['name', 'age', 'sayName']

//Object.getOwnPropertyNames返回所有实例属性

Object.getOwnPropertyNames(Person.prototype); //['constructor', 'name', 'age', 'sayName']

Object.getOwnPropertyNames(person);           //['name', 'age', 'sayName']
//更简单的原型语法

function People(){

}

People.prototype = {

      // constructor:People,

      name:'KKK',

      age:19,

      job:'boss',

      sayName:function(){

         console.log(this.name);

      }

}

var friend = new People()

console.log(friend.constructor);
//ƒ Object()   
//此时的constructor不再指向People,而是指向Object构造函数,如果constructor很重要,可以设置constructor:People,如上所示,此时[[Enumerble]]特性被设置为true

//重设构造函数,只适用于ECMAScript5兼容的浏览器

Object.defineProperty(People.prototype,'constructor',{

      enumerable:false,

      value:People

})

console.log(friend.constructor);    //f People(){}
//原型的动态性

//1、

function People(){

}

People.prototype = {

      constructor:People,

      name:'KKK',

      age:19,

      job:'boss',

      sayName:function(){

        	console.log(this.name);

      }

}

var friend = new People()//创建

People.prototype.sayNo = function(){console.log("NoNoNo");}

friend.sayNo()//NoNoNo

function People1(){     //1

}

var friend1 = new People1();//创建实例  引用的是原来的原型,此时创建的friend实例没有sayName方法

People1.prototype = {   //2、重写了原型

  constructor:People1,

  name:'KKK',

  age:19,

  job:'boss',

  sayName:function(){

    console.log(this.name);

  }

}

var friend2 = new People1(); //创建实例  引用的是重写后的原型,此时创建的friend2实例有sayName方法

friend1.sayName()   //error    报错

friend2.sayName()   //KKK 
//原型对象问题

People.prototype.friends = ['a','b']

var friend3 = new People()

var friend4 = new People()

friend3.friends.push('c')  //friend3修改了原型中共享的friends属性,这时friend4指向的同一个friends也更改了

console.log(friend3.friends);//['a', 'b', 'c']

console.log(friend4.friends);//['a', 'b', 'c']

2.4、结合使用构造函数模式和原型模式

function Unite(name,age,job){

  this.name = name

  this.age = age

  this.job = job

  this.friends = ['She','He']

}

Unite.prototype = {

  constructor:Unite,

  sayName:function(){

     console.log(this.name);

  }

}

var unite1 = new Unite('YY',18,'cooker')

var unite2 = new Unite('ZZ',21,'painter')


unite1.friends.push('It') //修改的是实例的属性


console.log(unite1.friends);//['She', 'He', 'It']

console.log(unite2.friends);//['She', 'He']


console.log(unite1.friends == unite2.friends);//false

console.log(unite1.sayName == unite2.sayName);//true

2.5、动态原型模式

(不能使用对象字面量重写原型)

function DynamicPrototype(name,age){

  this.name = name

  this.age = age

  //方法

  if(typeof this.sayName != "function"){

      DynamicPrototype.sayName = function(){

      console.log(this.name);

    }

  }

}

console.log(DynamicPrototype.prototype);

var dp = new DynamicPrototype('SS',32)

2.6、寄生构造函数模式

function ParasiticModels(name,age,job){

  var obj = new Object()

  obj.name = name

  obj.age = age

  obj.job = job

  obj.sayName = function(){

    console.log(this.name);

  }

  return obj;

}

var parasiticModels = new ParasiticModels('寄生',13,'程序员');

parasiticModels.sayName() //Loly

2.7、稳妥构造函数模式

创建对象的实例方法时不引用this,不使用new操作符调用构造函数

function SafeModel(name,age,job){

  var obj = new Object();

  //可以在这里定义私有变量和函数



  //添加方法

  obj.sayName = function(){

    console.log(name);

  };

  return obj;

}

var safeModel = SafeModel('稳妥',21,'boss')

safeModel.sayName()  //只能访问到sayName()方法,无法访问其他数据成员

你可能感兴趣的:(笔记,javascript,前端)