您的位置:首页 > Web前端 > JavaScript

Javascript 面向对象编程

2017-02-13 15:58 225 查看
Javascript 面向对象编程(一):封装

Javascript面向对象编程(二):构造函数的继承

Javascript面向对象编程(三):非构造函数的继承

/**
* 封装
*
* 为了解决从原型对象生成实例的问题,Javascript提供了一个构造函数(Constructor)模式。
* 所谓"构造函数",其实就是一个普通函数,但是内部使用了this变量。对构造函数使用new运算符,
* 就能生成实例,并且this变量会绑定在实例对象上。
*
* Javascript规定,每一个构造函数都有一个prototype属性,指向另一个对象。
* 这个对象的所有属性和方法,都会被构造函数的实例继承。
* 这意味着,我们可以把那些不变的属性和方法,直接定义在prototype对象上。
*/
// function Cat(name,color){
// this.name = name;
// this.color = color;
// }
// Cat.prototype.type = "猫科动物";
// Cat.prototype.eat = function(){alert("吃老鼠")};

/**
* 构造函数的继承
*
* 怎样才能使"猫"继承"动物"呢?
* 第一种方法也是最简单的方法,使用call或apply方法,将父对象的构造函数绑定在子对象上,即在子对象构造函数中加一行:
* Animal.apply(this, arguments);
*/
// function Animal(){
// this.species = "动物";
// }
// function Cat(name,color){
// this.name = name;
// this.color = color;
// }
// function Cat(name,color){
// Animal.apply(this, arguments);
// this.name = name;
// this.color = color;
// }
// var cat1 = new Cat("大毛","黄色");
// alert(cat1.species); // 动物
/**
* 第二种方法更常见,使用prototype属性,
* 我们将Cat的prototype对象指向一个Animal的实例
* Cat.prototype = new Animal();
  Cat.prototype.constructor = Cat;
  var cat1 = new Cat("大毛","黄色");
  alert(cat1.species); // 动物

第三种方法是对第二种方法的改进,直接继承Animal.prototype。
Cat.prototype = Animal.prototype;
  Cat.prototype.constructor = Cat;
  var cat1 = new Cat("大毛","黄色");
  alert(cat1.species); // 动物
与前一种方法相比,这样做的优点是效率比较高(不用执行和建立Animal的实例了),比较省内存。
缺点是 Cat.prototype和Animal.prototype现在指向了同一个对象,那么任何对Cat.prototype的修改,
都会反映到Animal.prototype。

四、 利用空对象作为中介
var F = function(){};
  F.prototype = Animal.prototype;
  Cat.prototype = new F();
  Cat.prototype.constructor = Cat;
F是空对象,所以几乎不占内存。这时,修改Cat的prototype对象,就不会影响到Animal的prototype对象。
可以将空对象作为中介封装为extend函数,很多库都有这个方法
*/

/**
* new操作符具体干了什么呢?
* 1、创建一个空对象,并且 this 变量引用该对象,同时还继承了该函数的原型。
2、属性和方法被加入到 this 引用的对象中。
3、新创建的对象由 this 所引用,并且最后隐式的返回 this 。
*/

/**
* js面向对象,多种创建对象方法!
* 1.对象字面量。
* 2.创建Object实例
* 2,构造函数模式
3,原型模式
4,混合构造函数和原型模式
*/

function Super(){
this.val = 1;
this.arr = [1];
}
function Sub(){
// ...
}
Sub.prototype = new Super(); // 核心

var sub1 = new Sub();
var sub2 = new Sub();
sub1.val = 2;
sub1.arr.push(2);
console.log(sub1.val); // 2
console.log(sub2.val); // 1

console.log(sub1.arr); // 1, 2
console.log(sub2.arr); // 1, 2
var sub3 = new Sub();
console.log(sub3.val); //1
// 原型对象的非引用属性属于每个对象的实例,原型对象的引用属性是所有实例共享的
//修改sub1.arr后sub2.arr也变了,因为来自原型对象的引用属性是所有实例共享的。
//这里的sub1.arr其实访问的是sub1.__proto__.arr,arr是一个数组对象,=指代的是一个内存地址的引用。
//避免对象共享可以参考经典的extend()函数,很多前端框架都有封装的,就是用一个空函数当做中间变量
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: