面向对象的程序设计

对于面向对象的程序设计的理解

理解对象

对象的定义:无序属性的集合,其属性可以包含基本值、对象或者函数。
如:

    var Person = {
        name : “Nicholas”,
    }

ECMAScript中有两种属性:数据属性和访问器属性。
数据属性有四个特性:
[[Configurable]]:表示能否通过 delete 删除属性从而重新定义属性,能否修改属性的特性,或者能否把属性修改为访问器属性。默认值为 true。
[[Enumerable]]:表示能否通过 for-in 循环返回属性。默认值为 true。
[[Writable]]:表示能否修改属性的值。默认值为 true。
[[Value]]:包含这个属性的数据值。读取属性值的时候,从这个位置读;写入属性值的时候,把新值保存在这个位置。这个特性的默认值为 undefined。
要修改默认属性,需使用ES5中的Object.defineProperty(),如:

Object.defineProperty(Person,“name”,{
       writable:false,
       value:“Nicholas”
})

访问器属性的四个属性:
[[Configurable]]: 同上
[[Enumerable]]:同上
[[Get]]:在读取属性时调用的函数,默认值为undefined
[[Set]]:在写入属性时调用的函数,默认值为undefined
访问器函数不能直接定义,必须使用Object.defineProperty()来定义,如:

var book={
   _year:2004,
   edition:1
};
Object.defineProperty(Person,“year”,{
       get:function(){
           return this._year;
}
set:function(newValue){
   if(newValue>2004){
this._year=newValue;
this.edition+=newValue-2004;
}
}
})
book.year=2005;
alert(book.edition);    //2

Object.getOwnPropertyDescriptor()方法获取给定属性的描述符,如:

var des=Object.getOwnPropertyDescriptor(book,”_year”);
alert(des.value)  //2004

创建对象

工厂模式

function createPerson(name){
  var o=new Object();
o.name=name;
return o;
}
var person1=createPerson(“Grey”)
2.2 构造函数模式
function Person(name){
this.name=name;
this.sayName=function(){
  alert(this.name)
}
}
var person1=new Person(“Grey”)
var person2=new Person(“Nicholas”)

(1)person1.constructor == Person 实例的构造函数指向对象
(2)person1.sayName != person2.sayName
person1和person2的sayName()方法不是同一个Function的实例,ES中函数也是对象,因此每定义一个函数,就是实例化一个对象。

原型模式

function Person(){}
Person.prototype.name=“Nicholas”;
Person.prototype.sayName=function(){
  alert(this.name)
};
var person1=new Person()
var person1=new Person()

(1)对象中的所有属性和方法都是由所有实例共享的。

(2)默认情况下,所有原型对象都自动获得一个constructor。
Person.prototype指向原型对象,Person.prototype.constructor指向Person

(3)每个实例对象中包含一个指针[[Prototype]](无法访问),即_proto_,可以通过isPrototypeOf()来确定对象与实例是否存在这种关系。

alert(Person.prototype.isPrototypeOf(person1))  //true

(4)ES5中的Object.getPrototypeof()方法返回[[Prototype]],实际上就是对象的原型。

    alert(Object.getPrototypeof(person1) == Person.prototype)

(5)hasOwnProperty()方法检测一个属性是存在于实例中,还是存在原型中。

(6)ES5中Object.keys()方法,接收一个对象作为参数,返回一个包含所有可枚举属性的字符串数组。

    Object.keys(Person.prototype)   //name,sayName
更简单的原型语法(对象字面量)
function Person(){}
Person.prototype={
name:“Nicholas”;
sayName:function(){
   alert(this.name)
};
}
var frined=new Person();
alert(friend instanceof Person)   //true
alert(friend.constructor == Person)  //false

constructor属性不再指向Person,因为这里的语法本质上完全重写了默认的prototype对象。

继承

原型链

基本思想:利用原型让一个引用类型继承另一个引用类型的属性和方法。

function Animal(){
    this.species = "动物";
  }
Animal.prototype.getValue=function(){
	   return this.species;
	}
function Cat(name,color){
    this.name = name;
    this.color = color;
  }
Cat.prototype = new Animal();
Cat.prototype.getfood=function(){
	   return this.name
	}
var cat1 = new Cat("大毛","黄色");
console.log(cat1.prototype.getValue)   //动物
console.log(Animal.prototype.isPrototype(cat1))  //true

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

原型链的主要问题:包含引用类型值的原型属性会被所有实例共享。

借用构造函数

基本思想:在子类型构造函数内部调用超类型构造函数

function Animal(){
		this.colors=["red","blue"]
  }
function Cat(name,color){
        //继承了Animal
		 Animal.call(this);
    this.name = name;
    this.color = color;
  }
var cat1 = new Cat("大毛","黄色");
cat1.colors.push("black");   //["red", "blue", "black"]
var cat2=new Cat("小苗","黑色");
console.log(cat2.colors)   //["red", "blue"]

Cat的每个实例都会具有自己的colors属性副本。
问题:方法都在构造函数中定义,因此函数复用性无从谈起。

组合继承

基本思想:使用原型链实现对原型属性和方法的继承,而通过借用构造函数来实现对实例属性的继承。

   function Animal(){
    this.species = "动物";
		this.colors=["red","blue"]
  }
	Animal.prototype.getValue=function(){
	   return this.species;
	}
	function Cat(name,color){
		Animal.call(this);
    this.name = name;
    this.color = color;
  }
	
	Cat.prototype = new Animal();
	Cat.prototype.constructor=Cat;
	Cat.prototype.getfood=function(){
	   return this.name
	}
	var cat1 = new Cat("大毛","黄色");
	cat1.colors.push("black");
	console.log(cat1.colors)    //["red", "blue", "black"]
    console.log(cat2.name)   //大毛
	var cat2=new Cat("小苗","黑色");
    console.log(cat1.colors)    //["red", "blue"]
    console.log(cat2.name)   //小苗

最常用的继承模式

原型式继承

利用一个空对象作为中介

    function extend(Child, Parent) {

    var F = function(){};
    F.prototype = Parent.prototype;
    Child.prototype = new F();
    Child.prototype.constructor = Child;
    Child.uber = Parent.prototype;
  }
       extend(Cat,Animal);
  var cat1 = new Cat("大毛","黄色");
  alert(cat1.species); // 动物
  ```
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值