面向对象与原型理解笔记

来源:互联网 发布:对撞机 知乎 编辑:程序博客网 时间:2024/05/16 05:11

    
  <script >




1.创建一个对象,基本方法
var obj=new Objiect();
 obj.name=name;
 obj.run=function run () {
   return obj.name;
 }
 这种方法如果还要创建类似的对象,就要重写上面的过程,代码重复写了
 所以用工厂模式
 2,工厂模式
 function createObject () {
   var obj=new Object();
   obj.name=name;
 obj.run=function run () {
   return obj.name;
 }
 return obj;
 }


这种办法解决了第一种的缺点,但是,创建出来的对象,无法识别,都是object,
所以有了构造函数穿件对象
3.构造函数创建对象
function Box () {
  this.name=name;
  this.age=age;
  this.run=function run () {
   return this.name+this.age;
}


其中的this指向创建出来的新的对象实例
这里没有new Object,为什么可以实例化Box()呢
它的过程如下:
  1.首先当使用new构造函数,后台自动 new Objeck();
  2,讲构造函数的作用域给新对象,而函数体内的this指向new Object()出来的对象,
  3,执行函数体内的代码,
  4,后台直接返回新对象
构造函数必修用new运算符调用,谨记


构造函数法创建的对象,每次都要为新对象在栈和堆中分配新的内存空间,特别是堆中的内存空间。如果大了创建对象,系统性能下降厉害
是否可以找到办法,使堆中的对象共同属性不被重复创建,而只是在栈中存在它的引用地址呢?
有,这就出现了原型概念


4.通过原型创建对象,
原型是个对象,它里面的属性和方法,被实例化的对象共享。


改变实例中的原型属性,对原型本来的属性没有影响。(即对其他实例的从原型中获得的属性没有影响)


原型中的属性和方法只能通过修改原型本身修改,也就是重写原型


原型创建的对象,被实例化后,不同的实例之间,原型指向相同的位置,而不只是引用。即在不同的实力的原型,在堆中只有一个位置。
function Box () {
  this.name=name;
  this.age=age;
  this.run=function run () {
   return this.name+this.age;
}
Box.prototype.sum=function sum () {
  return this.age+this.name+'nihao'
}
或者
Box.prototype={
  sum:function sum () {
  return this.age+this.name+'nihao'
}
}


原型链,就是原型共享遵循的规则
1.先在实例的构造函数里找,有就返回
2,如果构造函数里没有,则去他的第一级原型里找,有就返回,没有继续向下一级原型中找,知道找到为止,如果都没有,就返回undefiend,
3。所有对象的原型最后都能指向Object()的原型,即null(里面什么也么有)
4.Object()相当于空白对象




function Box () {
  
}


Box.prototype.sum=function sum () {
  return this.age+this.name+'nihao'
  }
  Box.prototype.name=name;
  Box.prototype.age=18;
  Box.prototype.time=12;






var box1= new Box()
box1.time=15
alert(box1.time)     /15
var box2= new Box()   
alert(box2.time)     /12


我们可以通过实例访问保存原型中的属性和方法,但不能通过实例重写原型中的值


那么怎么判断这个属性,是构造函数的实例中,还是原型中的属性呢


我们可以用hasOwnProterpy()函数
语法:box.hasOwnProperty('name') /box实例中是否有属性'name'
有返回true,没有返回flase.


我们还可以用:
 'name' in box;
 来判断属性是否在实例和原型中
 如果只在一个中,或者2个中都在,返回true,
 一个都在在,则返回false;


 有了上面的检测办法,我们可以写出 检测属性在原型中 的方法


 function isProperty (object property) {
   return !object.hasOwnProperty('property')&&'property'in object
  
 };
 var box= new Box()
 alert(isProperty(box,name))   /true


 通过原型创建的对象,1,它不能传参数,所以创建的初始值都一样,实际意义不大,
 而且他的最大优点共享,也是个最大的缺点,因为修改一个实例从原型中获得的属性值,就相当于修改了原型中的属性值,导致其他后面实例化得值也会修改


 这样我们就需要一种这样的方法,初始化需要得到不同值的属性和方法能得到不同的值,而不需要不同值得属性和方法,可以得到一样的属性和方法。有没有这样的方法呢?
 有
 5.构造函数+原型模式创建 对象
 function Box (user,age) {
   this.user=user;
   this.age=age;
   
 }
 Box.prototype={
  info:'dajiahao'
  run:function run () {
    return 'sb'
  }
 }
 var box1=new Box('le',11)
 alert(box1.name)
 var box2=new Box('ta',22)
 alert(box2.name)


这种方法很怪异,最好把构造函数和原型封装到一起
而且,每次调用原型中的方法,都会初始化原型中的方法
所以有了改进方法
6.动态原型模式     (我们一般用这种办法)
function Box (user,age) {
  this.user=user;
  this.age=age;
  if (!typeof this.run='function') {
    Box.prototype.run=function run () {
    return 'sb'
  }
  };
  
}


7.特殊的创建原型的方法
 1.寄生构造函数
 其实就是工厂模式+构造函数
 它解决了这样一个问题,JS中的内置对象,如果想创建新的方法,可以用他,如果用上面的原型模式+构造函数创建,例如String.prototype.add(),
 会引起其他string的不便和混乱
 function myString (string) {
   var str=new String(string)
   str.addstring=function  () {
     return this+",被添加了"
   }
   return str
 }
var box= new myString('lee')
alert(box.addstring());


给要真正执行的函数套个函数壳子,巧妙






继承
1.通过原型链继承
function Box () {
  this.fimily=[1,2,3,4]
}


function Desk () {
  
}


Desk.prototype=new Box();
var a=new Desk();
alert(a.fimily)


上面有上面缺点呢,
  1.如果重写a的原型(即通过实例修改原型的值),其他实例通过原型获得属性和方法得值也会被重写
  2.写出来的实例初始值都一样,也就是无法传参数改变初始值


2.对象冒充,或者叫经典继承,解决了上面2个缺点,因为他传参数了,所以不用从写原型
function Box (age,name) {
  this.name=name;
  this.age=age;
  this.run=function run (argument) {
    return this.age+this.name;
  }
}


function Desk (age,name) {
  Box.call(this,age,name)
}


var desk=new Desk('lee',18)
alert(desk.run())


这种方法只是借用函数,没有原型,无法复用(即封装起来,给其他对象用)
为了解决复用问题,有了下面方法
原型链+对象冒充模式,(组合继承)
function Box (name,age) {
  this.name=name;
  this,age=age;
  Box.prototype.run=function () {       
  return this.name + this.age;
  }
}
function Desk (name,age) {
  Box.apply(this,[name,age])
}
Desk.prototype=new Box();
var desk=Desk('ke',18)
alert(desk.run())


组合继承一般很常用,但有一个问题,就是超类型在使用过程中会被调用2次:一次是创建子类的时候,一次是在子类型构造函数内部对象冒充处。消耗系统性能
为了解决这个问题有了,寄生组合继承
通过一个中转函数,一个寄生函数,实现继承
中转函数
function obj(o) {
  function F() {}
  F.prototype = o;
  return new F();
}
寄生函数
function create(box, desk) {
  var f = obj(box.prototype);
  f.constructor = desk;         /不加这句,desk指向box的原型了
  desk.prototype = f;
}
function Box(name) {
  this.name = name;
  this.arr = ['哥哥','妹妹','父母'];
}


Box.prototype.run = function () {
  return this.name;
};


function Desk(name, age) {
  Box.call(this, name);         //第二次调用Box
  this.age = age;
}


// Desk.prototype = new Box();  /这句话被寄生继承替代了
create(Box,Desk)
var desk=new Desk('lee',100)
alert(message)


</script>















































 


  





































































    






0 0