面向对象的程序设计

构造函数模式

function Person(name, age, job){
    this.name = name
    this.age = age
    this.job = job
    this.sayName = function(){
        alert(this.name)
    }
}
var person1 = new Person('Nich', 20, 'developer')
var person2 = new Person('Gerg', 18, 'designer')
  1. new 操作符

    1. 创建一个新对象
    2. 将构造函数的作用域赋给新对象(this指向新对象)
    3. 执行构造函数中的代码(为这个新对象添加属性)
    4. 返回新对象
      构造函数创建的对象有全新的作用域,所以实例的方法和属性都是私有的
      person1.sayname === person2.sayName //false
  2. instanceof 操作符
    检测对象类型

    person1 instanceof Object //true
    person1 instanceof Person //true
    
  3. constructor属性
    构造函数创建的实例都有一个constructor属性,该属性指向构造函数

    person1.constructor === Person //true
    
  4. 构造函数的问题
    构造函数创建的实例,会导致不同的作用域链和标识符解析。换句话说,不同实例上的方法是不相等的。创建多个完成相同任务的方法是不必要的。
    解决方法:将函数定义转移到构造函数外部

    function Person(name, age, job){
        this.name = name
        this.age =age
        this.job = job
        this.sayName = sayName
    }
    function sayName() {
        alert(this.name)
    }
    

    这样就能实现所有实例的共用方法。如果对象需要定义很多方法,就需要定义多个全局变量。也就没有封装性可言了。我们可以使用原型模式来解决这个问题。

原型模型

function Person(){}
Person.prototype.name = 'Nico'
Person.prototype.age = 18
Person.prototype.sayName = function(){
    alert(this.name)
}
var person1 = new Person()
var person2 = new Person()
面向对象的程序设计_第1张图片
屏幕快照 2018-11-02 05.41.25.png
  1. Object.getPrototypeOf()
    Person.prototype.isPrototypeOf(person1) //true
  2. 如果像实例添加原型同名属性,将会屏蔽原型属性(原型链),即使设为null。要想重新访问原型属性,可以使用delete操作符
  3. in操作符
    通过对象能够访问给定属性时返回true,无论属性属于实例还是原型。
    4.简洁的原型语法
    function Person(){}
    Person.prototype = {
        name: 'Nico'
        age: 19
        job: 'developer'
        sayName: function(){
            alert(this.name)
        }
    }
    
    这种写法相当于重写prototype属性,因此constructor属性指向Object,可以手动设置
    constructor: Person
  4. 原型的动态性
    在原型中查找值的过程是一次搜索,因此我们对原型对象的任何修改都能从实例上反映出来。
    var friend = new Person()
    Person.prototype.sayHi = function(){
        alert('hi')
    }
    friend.sayHi() //'hi'(没问题)
    
    实例与原型之间的连接是一个指针,而非副本。
    如果是重写整个原型对象,就会切断构造函数与最初原型之间的联系。实例中的指针仅指向原型,而不指向构造函数
    function Person(){}
    var friend = new Person()
    Person.prototype = {
        constructor: Person
        name: 29
        job: 'developer'
        sayName: function(){
            alert('this.name')
        }
    }
    friend.sayName() //error
    
面向对象的程序设计_第2张图片
屏幕快照 2018-11-02 05.59.38.png
  1. 原型对象的问题
    原型中的所有属性都是被实例共享的。当我们需要定义私有属性的时候就有些不方便了。
    所以,较好的方式是结合构造函数模式和原型模式

组合使用构造函数模式和原型模式

构造函数模式用于定义实例属性,原型模式用于定义方法和共享的属性

function Person(name, age, job){
    this.name = name
    this.age = age
    this.job = job
    this.friends = ['a', 'b']
}
Person.prototype = {
    constructor: Person,
    sayName: function(){
        alert(this.name)
    }
}

本篇文章是 JavaScript高级程序设计__面向对象的程序设计 部分的读书笔记。刚接触js的时候读了一遍,在写了js一段时间后再读一遍,收获颇丰。文章写得浅显易懂,思路清晰,强烈建议有需要了解这部分知识的阅读原文。

你可能感兴趣的:(面向对象的程序设计)