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)