• JS面向对象与原型


    面向对象与原型
    一、创建对象
    1、基本方法

     1 var box = new Object();    //创建对象
     2 box.name = 'Lee';        //添加属性
     3 box.age = 100;
     4 box.run = function(){    //添加方法
     5     return this.name + this.age + '运行中...';    //this表示当前作用于下的对象
     6 };
     7 
     8 alert(box.run());
     9 
    10 alert(this.anme);    //这里的this代表的是window

    2、工厂模式

     1 //创建一个集中实例化的函数
     2 function createObject(name,age){
     3     var obj = new Object();            //创建对象
     4     obj.name = name;                //添加属性
     5     obj.age = age;
     6     obj.run = function(){            //添加方法
     7         return this.name + this.age +'运行在...';
     8     };
     9     return obj;                        //返回对象引用
    10 }    
    11 
    12 var box1 = new createObject('Lee',100);        //创建第一个对象
    13 var box2 = new createObject('Jack',200);    //创建第二个对象
    14 
    15 alert(box1.run());                            //打印第一个对象实例的run()方法
    16 alert(box2.run());           

    3、构造函数

    1 function Box(name,age){    //创建一个对象
    2     this.name = name;    //添加一个属性
    3     this.age = age;
    4     this.run = function(){    //添加一个方法
    5         return this.name + this.age + '运行中...';
    6     };
    7 }

    注意事项:
    (1).构造函数也是函数,但函数名第一个字母必须大写
    (2).必须new构造函数名()
    (3).必须使用new运算符,用普通函数调用一般无效
    构造函数和普通函数的唯一区别,就是他们调用的方式不同。只不过,构造函数也是函数,必须用new运算符来调用,否则就是普通函数。

    使用了构造函数的方法,和使用工厂模式的方法他们不同之处如下:

    1.构造函数方法没有显示的创建对象(new Object());

    2.直接将属性和方法赋值给this对象;

    3.没有renturn语句。

      构造函数方式

    原型模式方法

    在原型模式声明中,多了两个属性,这两个属性都是创建对象时自动生成的。__proto__属性是实例指向原型对象的一个指针,它的作用就是指向构造函数的原型属性constructor。通过这两个属性,就可以访问到原型里的属性和方法了。

    二、原型
    //原型实例

    1 function Box(){} //构造函数体内什么都没有,这里如果有,叫做实例属性,实例方法
    2 
    3 Box.prototype.name = 'Lee';    //添加原型属性
    4 Box.prototype.age = 100;    //添加原型属性
    5 Box.prototype.run = function(){    //添加原型方法
    6   return this.name + this.age + '运行中...';
    7 };

    原型模式的执行流程:
    1.先查找构造函数实例里的属性或方法,如果有,立刻返回;
    2.如果构造函数实例里没有,则去它的原型对象里找,如果有,就返回;

    原型的声明是有先后顺序的,所以,重写的原型会切断之前的原型。

    //使用字面量方式创建原型
    1
    function Box() {}; 2 Box.prototype = { //使用字面量的方式,这里{}就是对象,是Object,{}就相当于new Object 3   name : 'Lee', 4   age : 100, 5   run : function () { 6    return this.name + this.age + '运行中...'; 7   } 8 };

    原型的优点 -- 共享 -- 也是缺点
    解决缺点方式
    1、组合构造函数+原型模式

     1 function Box(name,age){    //保持独立的用构造函数
     2   this.name = name;
     3   this.age = age;
     4   this.family = ['哥哥','姐姐','妹妹'];
     5   }
     6 
     7   Box.prototype = {    //保持共享的用原型模式
     8   constructor : Box,
     9   run : function(){
    10     return this.name + this.age + "运行中...";
    11   }
    12 };

    2、动态原型模式

     1 //使用此方法,不可以再使用字面量的方式重写原型,因为会切断实例和新原型之间的联系
     2 //可以将原型封装到构造函数里
     3 function Box(name,age){    
     4   this.name = name;
     5   this.age = age;
     6   this.family = ['哥哥','姐姐','妹妹'];
     7 
     8   //原型的初始化,只要一次初始化就可以了,没必要每次构造函数实例化的时候都初始化
     9   if(typeof this.run != 'function'){    //判断this.run是否存在
    10     Box.prototype.run = function(){
    11       return this.name + this.age + "运行中...";    
    12     };
    13   }
    14 }

    3、寄生构造函数(= 工厂模式 + 构造函数)

    1 function Box(name,age){
    2   var obj = new Object();
    3   obj.name = name;
    4   obj.age = age;
    5   obj.run = function(){
    6     return this.name + this.age + "运行中...";    
    7   }
    8   return obj;
    9 }

    4、稳妥构造函数

    1 //在一些安全环境中,如禁止使用this(构造函数里不使用this)和new(外部实例化构造函数不使用new)
    2 function Box(name,age){
    3     var obj = new Object();
    4     obj.run = function(){
    5     return name + age + "运行中...";    //直接打印参数即可    
    6     }
    7     return obj;  
    8 }  

    三、继承
    1、通过原型链继承

     1 function Box(){    //被继承的函数叫做超类型(父类,基类)
     2 // this.name = 'Lee';
     3 }
     4 
     5 Box.prototype.name = 'Jack';
     6 
     7 function Desk(){    //继承的函数叫做子类型(子类,派生类)
     8 this.age = 100;
     9 }
    10 
    11 //通过原型链继承
    12 Desk.prototype = new Box();
    13 
    14 var desk = new Desk();
    15 alert(desk.name);    //就近原则,实例里有就返回,没有就去查找原型

    2、借用构造函数继承(对象冒充继承)

     1 function Box(age) {
     2   this.name = ['Lee', 'Jack', 'Hello']
     3   this.age = age;
     4 }
     5 
     6 function Desk(age) {
     7   Box.call(this, age);    //对象冒充,给超类型传参
     8 }
     9 
    10 var desk1 = new Desk(200);
    11 alert(desk1.age);
    12 alert(desk1.name);
    13 desk1.name.push('AAA');    //添加的新数据,只给desk
    14 alert(desk1.name);
    15 
    16 var desk2 = new Desk(200);
    17 alert(desk2.name);

    3、组合继承(=原型链+借用构造函数)

     1 function Box(age) {
     2   this.name = ['Lee', 'Jack', 'Hello']
     3   this.age = age;
     4 }
     5 
     6 Box.prototype.run = function () {    
     7   return this.name + this.age;
     8 };
     9 
    10 function Desk(age) {
    11   Box.call(this, age);    //对象冒充
    12 }
    13 
    14 Desk.prototype = new Box();    //原型链继承
    15 
    16 var desk = new Desk(100);
    17 alert(desk.run());

    4、原型式继承

     1 //临时中转函数
     2 function obj(o){    //o表示将要传递进入的一个对象
     3   function F(){}    //F构造是一个临时新建的对象,用来存储传递过来的对象
     4   F.prototype = o;    //将o对象实例赋值给F构造的原型对象
     5   return new F();    //最后返回这个得到传递过来对象的对象实例
     6 }
     7 
     8 //这是字面量的声明方式,相当于 var box = new Box();
     9 var box = {
    10   name : 'Lee',
    11   age : 100,
    12   family : ['哥哥','姐姐','妹妹']
    13 };
    14 
    15 //box1就等于new F()
    16 var box1 = obj(box);
    17 // alert(box1.name);
    18 alert(box1.family);
    19 box1.family.push('弟弟');
    20 alert(box1.family);
    21 
    22 var box2 = obj(box);
    23 alert(box2.family);    //引用类型的属性共享了

    5、寄生式继承(=原型式+工厂模式)

     1 //临时中转函数
     2 function obj(o){    //o表示将要传递进入的一个对象
     3   function F(){}    //F构造是一个临时新建的对象,用来存储传递过来的对象
     4   F.prototype = o;    //将o对象实例赋值给F构造的原型对象
     5   return new F();    //最后返回这个得到传递过来对象的对象实例
     6 }
     7 
     8 //寄生函数
     9 function create(o){
    10   var f = obj(o);
    11   f.run = function(){
    12     return this.name + "方法";
    13   }
    14   return f;
    15 }
    16 
    17 //这是字面量的声明方式,相当于 var box = new Box();
    18 var box = {
    19   name : 'Lee',
    20   age : 100,
    21   family : ['哥哥','姐姐','妹妹']
    22 };
    23 
    24 var box1 = create(box);
    25 alert(box1.run());

    6、寄生组合继承

     1 //临时中转函数
     2 function obj(o){    //o表示将要传递进入的一个对象
     3   function F(){}    //F构造是一个临时新建的对象,用来存储传递过来的对象
     4   F.prototype = o;    //将o对象实例赋值给F构造的原型对象
     5   return new F();    //最后返回这个得到传递过来对象的对象实例
     6 }
     7 
     8 //寄生函数
     9 function create(box, desk){
    10   var f = obj(box.prototype);
    11  f.constructor = desk;    //调整原型构造指针
    12   desk.prototype = f;
    13 }
    14 
    15 function Box(name,age){
    16   this.name = name;
    17   this.age = age;
    18 }
    19 
    20 Box.prototype.run = function(){
    21   return this.name + this.age + '运行中...';
    22 };
    23 
    24 function Desk(name,age) {
    25   Box.call(this, name, age);    //对象冒充
    26 }
    27 
    28 //通过寄生组合继承来实现继承
    29 create(Box,Desk);    //这句话用来替代Desk.prototype = new Box()
    30 
    31 var desk = new Desk('Lee',100);
    32 alert(desk.run());
    33 alert(desk.constructor);

    使用了构造函数的方法,和使用工厂模式的方法他们不同之处如下:

    1.构造函数方法没有显示的创建对象(new Object())

    2.直接将属性和方法赋值给this对象;

    3.没有renturn语句。

  • 相关阅读:
    模态对话框
    js小练习题
    js练习题
    python实现不同格式九九乘法表
    Python学习笔记之疑问12:什么是tuple
    Python学习笔记之疑问11:批量赋值
    Python学习笔记之疑问10:如何使用分隔符连接list中的字符串
    Python学习笔记之疑问 9:如何使用For语句
    Python学习笔记之疑问 8:Python 中的问号表达式
    Python学习笔记之疑问 7:自定义模块放在什么位置
  • 原文地址:https://www.cnblogs.com/xlb-happymoment/p/6686755.html
Copyright © 2020-2023  润新知