js高级程序设计第3版(6章:面向对象的程序设计)

1.理解对象

2.属性类型

  •  数据属性:[Configurable]是否删除,编辑的特性。[Enumerable]表示能否通过for-in循环返回该属性。[Wirtable]表示能否修改属性的值 [value]包含这个属性的数据值

   修改这些属性的值时,Object.defineProperty() 不传参时,默认三个属性是false 

  • 访问器属性:[Configurable]是否删除,编辑的特性。[Enumerable]表示能否通过for-in循环返回该属性。[Get]在读取属性时调用的函数,默认undefined 。[Set]在写入属性调用的函数,默认为undfined
  • 读取属性的特性  Object.getOwnPropertyDescriptor()

3.创建对象

  • 工厂模式:优点:解决创建多个相似对象的问题,   缺点:没有解决对象识别的问题
function person(){
  var o=new Object();
  o.name=name;
  o.job=job;
  return o;
}
var person1=person("122");
var person2=person("232")
  
  • 构造函数模式: 优点:创造的自定义的构造函数可以作为实例标识 instanceof      缺点:每次创建一个实例,则重新定义方法,容易造成乱用。放在全局也容易混淆。
function Createperson(name,age){
     this.name=name;
     this.age=age;
     this.sayName=function(){
       alert(this.name)
    }
}
var person1=new Createperson('12',1);
var person2=new Createperson('1222',33);
  • 原型模式:优点:所有的属性和函数都可以共享       缺点: 引用类型共享,造成所有的实例的对象属性都一样,没有差异性

      Object.getPrototypeOf()获取原型对象

               Object.hasOwnProperty()可以检测一个属性是存在于实例中,还是原型中   来自实例则返回true。实例和原型 中同时存在相同的变量,则优先使用实例中,delete 实例中则会访问到原型中的

                in操作符:无论在实例和原型中都会返回true。

  • 组合构造函数和原型模式:共享的属性采用构造函数,共同的方法采用原型方法(默认方式)
  • 动态原型模式:

 

function  Person (name,age,job){
       this.name=name;
       this.age=age;
       this.job=job;
   if(typeof this.sayName!='function'){
    Person.prototype.sayName=function(){
       alert(this.name)
   }
}
  • 寄生构造函数模式:在构造函数中,创建对象,封装对象的属性,方法等,然后返回对象

         缺点:返回的对象与构造函数和构造函数的原型都没有关系,采用instanceof确定类型。

  • 稳妥构造函数模式:在一些安全环境中,禁止使用this和new使用。访问函数中的变量,只能使用函数中的方法。

4.继承:实现继承(依靠原型链实现)接口继承(因没有函数签名,没有此种方法)    

 

  •  原型链继承:注意:通过此方法继承时,不能使用对象字面量创建原型方法,因为会重写原型链。

  缺点:1.引用类型的原型共用,会影响所有的实例。2.构建实例时,不能向里边传入参数。不能与构造函数一样。

  • 借用构造函数继承:
       function Person(name){
         this.name=name;
       }
       function Second(){
         //即传入参数,又定义自己的属性
        Person.call(this,'qwqw')
        this.age=12;
       }
       let s=new Second();
       console.log('s.name',s.name);
       console.log('s.age',s.age);

      缺点:方法都在构造函数中定义,函数不能复用。

  • 组合继承:原型链实现对原型属性和方法的继承,构造函数实现对实例属性的继承。(组合)
    function Person(name) {
      this.name = name;
      this.colors = ['red', 'green']
    }
    Person.prototype.sayName = function () {
      alert(this.name);
    }
    function Second(name, age) {
      Person.call(this, name)
      this.age = age;
    }
    Second.prototype = new Person();
    Second.prototype.sayAge = function () {
      alert(this.age);
    }
    let s = new Second();
    let create1 = new Second('111', 1);
    create1.colors.push('black');
    console.log('1,colors', create1.colors);
    create1.sayName()
    create1.sayAge()
    let create2 = new Second('211', 2);
    console.log('2,colors', create2.colors);
    create2.sayName()
    create2.sayAge()
  • 原型式继承
    // 传入的参数作为构造函数的原型,本质是浅复制
    function object(o){
      function F(){};
      F.prototype=o;
      return new F();
    }
    var person={
      name:'ssss',
      friends:['k','l','o']
    }
    var another=object(person);
    another.name="another";
    console.log('anotjer',another.name);  // 'another'
    another.friends.push('sss');
    // another和person 同指一个地方
    console.log('as',another.friends);    //["k", "l", "o", "sss"]
    console.log('anotjeranotjer',person.friends);//["k", "l", "o", "sss"]

Object.create()接收两个参数:第一个参数:用作新对象原型的对象和(可选的)一个为新对象定义额外属性的对象。

    function object(o){
      function F(){};
      F.prototype=o;
      return new F();
    }
    var person={
      name:'ssss',
      friends:['k','l','o']
    }
    var another=Object.create(person,{
      name:{
        value:"SSS"
      }
    });
    alert(another.name)  //SSS
  • 寄生式继承
// 传入的参数作为构造函数的原型,本质是浅复制
    function object(o){
      function F(){};
      F.prototype=o;
      return new F();
    }
    // 类似寄生构造函数和工厂模式类似
    function Another(per){
      var clone=object(per); //通过调用函数创建一个新对象
      clone.sayhi=function(){//为新对象添加函数
        alert('hi')
      }
      return clone;
    }
  • 寄生组合式继承

  组合式继承有个缺点:原型上的属性和实例上的属性会被分别创建一次,实例上的属性如果和原型上的属性同名,则会屏蔽原型中的属性名。

    其继承的特点:借用构造函数实现属性的继承,通过原型链继承方法。

    // 传入的参数作为构造函数的原型,本质是浅复制
    function object(o){
      function F(){};
      F.prototype=o;
      return new F();
    }
    function inherit(subType,superType){
      // 第一个为子类型构造函数,第二个为超类型构造函数
      var prototype=object(superType.prototype); //创建超文本构造函数的一个副本
      prototype.constructor=subType; //增强对象
      subType.prototype=prototype;  //将对象赋值给子类型的构造函数

    }
    function SuperType(name){
      this.name=name;
      this.colors=['ee','e','eee']
    }
    SuperType.prototype.sayName=function(){
      alert(this.name)
    }
    function SubType(name,age){
      SuperType.call(this,name);
      this.age=age;
    }
    inherit(SubType,SuperType);
    SubType.prototype.sayAge=function(){
      alert(this.age);
    }
    let s=new SubType('ss',12);
    console.log('s',s);   //包含name,age,colors
    console.log('super',new SuperType('super')); //包含colors,name

 

posted @ 2021-02-07 15:05  yaqian96  阅读(63)  评论(0)    收藏  举报