♫【面向对象】

var Car = function() {
    this.init()
}
Car.prototype.init = function() {
    console.log(this)
}
function Person() {
    this.init()
}
Person.prototype.init = function() {
    console.log(this)
}
var car = new Car
var person = new Person
console.log(car.constructor) // function(){}
console.log(person.constructor) // function Person() {}

面向对象的 Javascript (声明篇)
http://www.gracecode.com/posts/934.html
面向对象的 Javascript (继承篇)
http://www.gracecode.com/posts/969.html

/**
 * 工厂模式 
 */
;(function() {
    function showColor() {
        console.log(this.color)
    }

    function createCar(sColor) {
        var oCar = new Object
        oCar.color = sColor || 'red'
        oCar.showColor = showColor

        return oCar
    }

    var oCar = createCar()
    oCar.showColor()
})()

/**
 * 构造函数模式
 * 构造函数返回的就是其this的值,所以不必使用return返回
 */
;(function() {
    function showColor() {
        console.log(this.color)
    }

    function Car(sColor) {
        this.color = sColor
        this.showColor = showColor
    }

    var oCar = new Car('red')
    oCar.showColor()
})()

/**
 * 混合模式 
 */
;(function() {
    function Car(sColor) {
        this.color = sColor
    }

    Car.prototype.showColor = function() {
        console.log(this.color)
    }

    var oCar = new Car('red')
    oCar.showColor()
})()

/**
 * 动态原型模式
 */
;(function() {
    function Car() {
        this.color = 'red'
        if (typeof Car._initialized === 'undefined') {
            Car.prototype.showColor = function() {
                console.log(this.color)
            }
            Car._initialized = true
        }
    }

    var oCar = new Car('red')
    oCar.showColor()
})()

/**
 * 混合工厂模式
 */
;(function() {
    function Car() {
        var oCar = {}
        oCar.color = 'red'
        oCar.showColor = function() {
            console.log(this.color)
        }

        return oCar
    }

    var oCar = new Car()
    oCar.showColor()
})() 

/**
 * 通常使用的是 混合模式 与 动态原型模式
 * 不过不要单独使用 工厂模式 与 构造模式 (或者其两者的结合体),因为这样会造成不必要的浪费
 /

Javascript 面向对象编程(一):封装
http://www.ruanyifeng.com/blog/2010/05/object-oriented_javascript_encapsulation.html
Javascript面向对象编程(二):构造函数的继承
http://www.ruanyifeng.com/blog/2010/05/object-oriented_javascript_inheritance.html
Javascript面向对象编程(三):非构造函数的继承
http://www.ruanyifeng.com/blog/2010/05/object-oriented_javascript_inheritance_continued.html

封装

/**
 * 对于每一个实例对象,type属性和eat()方法都是一模一样的内容,每一次生成一个实例,都必须为重复的内容,多占用一些内存
 */
;(function() {
    function Cat(name, color) {
        this.name = name
        this.color = color
        this.type = '猫科动物'
        this.eat = function() {
            console.log("吃老鼠")
        }
    }
    var cat1 = new Cat('大毛', '黄色')
    var cat2 = new Cat('大毛', '黄色')
    console.log(cat1.eat == cat2.eat)
})()

/* 
 * Javascript规定,每一个构造函数都有一个prototype属性,指向另一个对象。这个对象的所有属性和方法,都会被构造函数的实例继承
 * 这意味着,我们可以把那些不变的属性和方法,直接定义在prototype对象上
 * 这时所有实例的type属性和eat()方法,其实都是同一个内存地址,指向prototype对象,因此就提高了运行效率
 */
;(function() {
    function Cat(name, color) {
        this.name = name
        this.color = color
    }
    Cat.prototype.type = '猫科动物'
    Cat.prototype.eat = function() {
        console.log("吃老鼠")
    }
    var cat1 = new Cat('大毛', '黄色')
    var cat2 = new Cat('大毛', '黄色')
    console.log(cat1.eat == cat2.eat)
})()
function Cat(name, color) {
    this.name = name
    this.color = color
}

var cat1 = new Cat('大毛', '黄色')
console.log(cat1.name)

/**
 * constructor
 * cat1会自动含有一个constructor属性,指向它们的构造函数
 */
console.log(cat1.constructor === Cat)

/**
 * instanceof
 * 验证原型对象与实例对象之间的关系
 */
console.log(cat1 instanceof Cat)

Cat.prototype.type = '猫科动物'
Cat.prototype.eat = function() {
    console.log('吃老鼠')
}

/**
 * isPrototypeOf
 * 这个方法用来判断,某个proptotype对象和某个实例之间的关系
 */
console.log(Cat.prototype.isPrototypeOf(cat1))

/**
 * hasOwnProperty
 * 判断某一个属性到底是本地属性,还是继承自prototype对象的属性
 */
console.log(cat1.hasOwnProperty('type'), cat1.hasOwnProperty('name')) 

/**
 * in
 * in运算符可以用来判断,某个实例是否含有某个属性,不管是不是本地属性
 */
console.log('name' in cat1)
for (var prop in cat1) {
    console.log('cat1[' + prop + ']=' + cat1[prop])
}

构造函数的继承

function Animal() {
    this.species = '动物'
}
Animal.prototype.food = '食物' // 不变的属性都可以直接写入Animal.prototype
/**
 * 构造函数绑定
 */
function Cat(name, color) {
    Animal.apply(this, arguments)
    this.name = name
    this.color = color
}
var cat1 = new Cat('大毛', '黄色')
console.log(cat1.species)

/**
 * prototype模式
 */
function Dog(name, color) {
    this.name = name
    this.color = color
}
Dog.prototype = new Animal()
console.log(Dog.prototype.constructor == Animal)
Dog.prototype.constructor = Dog
var dog1 = new Dog('大毛', '黄色')
console.log(dog1.constructor == Dog.prototype.constructor)
console.log(dog1.constructor == Dog)
console.log(dog1.species)

/**
 * 利用空对象作为中介
 * Parent.prototype only
 * Child.uber 意思是为子对象设一个uber属性,这个属性直接指向父对象的prototype属性。(uber是一个德语词,意思是"向上"、"上一层"。)
 * 这等于在子对象上打开一条通道,可以直接调用父对象的方法。这一行放在这里,只是为了实现继承的完备性,纯属备用性质
 */
function Fish(name, color) {
    this.name = name
    this.color = color
}
function extend(Child, Parent) {
    var F = function() {}
    F.prototype = Parent.prototype
    Child.prototype = new F()
    Child.prototype.constructor = Child
    Child.uber = Parent.prototype
}
extend(Fish, Animal)
var fish1 = new Fish('大毛', '黄色')
console.log(fish1.food)

/**
 * 拷贝继承
 */
function People(name, color) {
    this.name = name
    this.color = color
}
function extend2(Child, Parent) {
    var p = Parent.prototype
    var c = Child.prototype
    for (var i in p) {
        c[i] = p[i]
    }
    c.uber = p
}
extend2(People, Animal)
var people1 = new People('大毛', '黄色')
console.log(people1.food)

非构造函数的继承

/**
 * object()方法
 */
var Chinese = {
    nation: '中国', // string
    city: ['杭州', '上海'], // object
    eat: function() { // function
        console.log('食物')
    }
} 
function object(o) {
    function F() {}
    F.prototype = o
    return new F()
}
var Doctor = object(Chinese)
Doctor.career = '医生'
console.log(Doctor.nation)

/**
 * 浅拷贝
 * 基本类型的数据
 */

/**
 * 深拷贝
 * 基本类型的数据
 */
function deepCopy(p, c) {
    var c = c || {}
    for (var i in p) {
        console.log(typeof p[i])
        if (typeof p[i] === 'object') {
            c[i] = (p[i].constructor === Array) ? [] : {}
            deepCopy(p[i], c[i])
        } else {
            c[i] = p[i]
        }
    }
    return c
}
Chinese.birthPlaces = ['北京','上海','香港']
var Teacher = deepCopy(Chinese)
Teacher.birthPlaces.push('厦门')
console.log(Chinese.birthPlaces)
console.log(Teacher.birthPlaces)
原文地址:https://www.cnblogs.com/jzm17173/p/3035727.html