`

javascirpt对象创建

 
阅读更多
javascript中的面向对象

理解js中的对象 最底层的对象Object;
每个函数对象都有一个prototype属性,prototype属性指向一个prototype(原型)对象,prototype对象有个constructor属性,contructor属性指向对象本身
ES5中对对象新增了一些数据属性,详细可自行搜索。比如,configurable(false,不可删除属性和不可修改非可写状态的属性),enumerrable(可枚举),writeable(可读写),通过Object.defineProperty(obj,propertyname,configrables); 关于Object对象的新增方法属性等,后续新开一篇写。另外要提一点:引用对象只能对源对象进行扩展而不能进行修。
  var  source = {"a":3,"b":4};//源对象 
  var  cpsource = source; 
  cpsource.c = 5;  
  //source.c 输出的是5 
  cpsource = {"c":5};  
  source.c //输出的是undefined
  //引用对象只能对源对象进行扩展而不能进行修改
对象创建的几种方式

直接量
var  Animal = {
      name:"cat",
      age : 2,
      move : function(){
          console.log(this.name +"---- move");
      }
 }
ES5原生支持的Object.create();

道格拉斯的对象创建模式,空壳函数实例(就是原生替代)。

 if (typeof Object.create !== 'function') {  
  Object.create = function (o) {  
      function F() {}  
      F.prototype = o;  
      return new F();  //返回的是函数的实例
  };  
}  
var newObject = Object.create(oldObject);  
工厂模式(没有解决对象识别以及重复的问题)
function createObject(){
      var o = new Object();
      o.xxx= "xxx";
      o.fn = function(){};
      return o;
}
构造函数模式(优点,有自己的特征和类型,可以用instanceOf判断其产生的实例.缺点,fn:共性的方法重复产生并且是不同实例)
function Animal(xxx){
      this.xxx = "xxx";
      this.fn = function(){
      }
}
var dog1 = new Animal(xxx);
var dog2 = new Animal(xxx);
//dog1的fn和dog2的fn是不同fn函数对象产生的不同实例,在js中函数也是对象,定义一个函数的时候就实例化了一个对象
//this.fn = function(){}-------------this.fn = new Function(参数....,函数体);
alert(dog instanceOf Animal);

dog1.fn == dog2.fn  //false--不同的实例对象,可以通过函数fn外置的方式实现,但是那样不如原型模式优美
原型模式(解决方法重复产生,方法和属性都在原型上。)
function Animal(xxx){


}
Animal.prototype.xxx = "xxx";
Animal.prototype.fn = function(){

};
Animal.prototype.constructor == Animal;//true

var cat = new Animal("cat");
cat.xxx="xiaoli";
var dog = new Animal("dog");
console.log(cat.xxx+"--------"+dog.xxx);// xiaoli--------xxx
//所有实例共享同一个原型对象,对象实例是更改不了原型属性中的值。后续的更改只起到了屏蔽的作用

换种方式,采用直接字面量的方式,重新原型属性指向的对象。
function Animal(xxx){


}

Animal.prototype = {
    xxx:"xxx",
    fn:function(){

    }
}

Animal.prototype.constructor == Object; //true
要更改过来也很简单
Animal.prototype = {
    xxx:"xxx",
    fn:function(){

    },
    constructor:Animal
}
//这样就可以指回自己了。

通过构造函数产生的实例,都会默认有个[prototype]的指针指向其最初的原型。修改原型为另外一个对象就等于切断了函数构造函数与其最初原型属性直接的联系;也就是会造成函数的prototype.constructor指向的不是函数原来的构造函数了。这样也就会造成一些使用上的麻烦,更改原型对象一定要确保在在函数实例化之前,否则会造成实例调用的属性或方法不存在的问题,因为这个时候联系已经被切断了。
function Animal(xxx){

}
var dog = new Animal();
Animal.prototype = {
name :"小飞",
fn : function(){
        console.log(this.name);
 }
}

dog.fn();//TypeError: undefined is not a function


原型模式的问题:没有传参了都要不断在原型上弄,原型上一个属性大家又是共享的,你改了,就会影响到别人,实例化之后大家的默认值都是一样的,其最大的问题就是如果是基本属性还好,因为别人可以更改来屏蔽,如果共享的属性是引用属性就会有问题了,因为引用属性修改的是其里面的值,对所有实例都有影响。原型上的方法共享是没有问题,不同的实例共享同一方法可以节约重复实例的情况。解决这个问题就要用到下面的混合型模式了。属性全部放在构造函数中,方法放在原型上。
混合型模式(构造函数+原型) 结构大概如下
function Animal(name,age){
    this.name = name;
    this.age = age;
    //.....
}
Animal.prototype.fn = function(){
//............
}
动态原型模式(就是把原型上对方法的定义全部封装在构造函数中,并且为了避免重复实例化会进行类型判断)

寄生构造函数模式 和工厂模式,构造函数类似。跟工厂模式不同的是他有自己的名称,跟构造函数不同的是他有返回。

function Animal(name){
  var o = new Object();
  o.name = name;
  o.fn = function(){}
  return o;
}
主要用途,在特殊情况下为对象创建构造函数,return 其实就是重写了构造函数调用时的返回值,默认情况是返回对象新产生的实例。
稳妥构造函数模式(禁止使用new和this的环境中使用) 特征:构造函数中没有没有属性,对象的实例没有new
function Animal(name){
  var o = new Object();
  o.fn = function(){
     console.log(name);
  }
}
var dog = Animal(name);
dog.fn();
也就是属性只能通过方法调用才能访问得到
上面几种都是比较经典的模式,我们用的最多的是混合型模式
javascript的继承

最常用的还是对象冒充+原型链;原型与实例之前的关系可以通过instanceof与构造函数.prototype.isPrototypeOf()
对象冒充+原型链demo:
function Animal(name,age,color){
this.name = name;
this.age = age;
this.color = color;
}

Animal.prototype.fn = function(){
 console.log("move dog color is: "+this.color[0]);
}

function Dog (name,age,color){
    Animal.call(this,name,age,color);//对象冒充,将当前对象的指针替换父类的指针,继承父类的构造函数属性

    this.name += "  feifei";
}
Dog.prototype = Animal.prototype;
//继承父类的原型属性和方法,这里如果改成Dog.prototype = new Animal();
//就会造成多个实例共享一个引用对象,解决办法就是构造空壳函数,这样
//改完之后是类继承,通过子类原型对象指向父类对象的实例

Dog.prototype.constructor = Dog;//构造函数指针指回本身

var smallDog = new Dog("xiaoniu",23,["yellow"]);

smallDog.fn();// move dog color is: yellow

var smallDog2 = new Dog("xiaoniu2",25,['yellow','red']);

console.log(smallDog.color  +"-----"+smallDog2.color);//["yellow"]----+["yellow","red"]


----------------------------------------------------------------------------------------------------
ES5中的规范对象的原型式继承方式
/***
适用场景:简单继承原始对象的情况,所有引用属性是共享的
a:子类原型对象(可选,不写就放到object上。。。)
b:新对象的额外属性{key:{
 value:value
}}
***/

Object.create(a,b);
demo:
var bb = {"name":"xiaofei","color":["yellow","red"]};
var aa = Object.create(bb);
console.log(aa.name);//xiaofei
console.log(aa.color[0]);
var aa2 = Object.create(bb,{"name":{
                    value:"xiaoniu"

}});
aa2.color[0]="blue";
 console.log(aa.color[0]);

console.log(aa2.name);//xiaoniu
VM1010:4 xiaofei
VM1010:5 yellow
VM1010:11 blue
VM1010:13 xiaoniu

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics