JavaScript学习笔记(三)
2015-06-05 21:09
701 查看
JavaScript面向对象程序设计
JS中也可以自己设计引用类型!
创建对象
(1)工厂模式:
(2)构造函数模式
当用构造函数创建一个实例之后(即new Constructor() ),会在返回的实例中自动添加一个__proto__属性,指向其构造函数的propotype属性。如图:
所以其实是靠constructor这些来进行类型识别的。使用构造函数模式的缺点是,每个方法都要在一个实例中创建一遍!可以用一下代码使方法公用:
(3)原型模式
原型模式即将属性和方法放在propotype而不是实例中,这样由于所有的Person的实例都指向同一个propotype,所以可以共享属性和方法。
共享基本类型的属性不是问题,当person.name="Ben"这样重新设置属性的时候,会在实例对象中重新加一个name属性,同时不修改propotype中的name属性,以后访问person.name根据原型链,会先在实例中找name属性,找不到才去propotype中找。这样就保证了每个实例的基本类型属性的独立。但是引用类型的属性,在修改时不会在实例中重建,所以原型模式有问题。
(4)组合原型模式和构造函数模式
将方法放在原型中,将属性放在构造函数中:
继承
(1)原型链
当把一个类的构造函数的propotype属性赋值为另一种类的实例对象时,就实现了继承。
如图,当把SubType的propotype设为:
那么可以在图中看到,继承之后,instance的propotype中有SuperType实例应有的getSuperValue方法,__proto__属性。就这样,通过__proto__指针形成一个原型链,实现继承关系。那么问题来了,由于会把实例整个赋值给propotype,因此propotype中会包含属性(严重的问题在于引用类型的属性)。
(2)借用构造函数
(3)组合继承
将父类属性先用借用构造函数的方法继承到实例中来,再用原型链复制父类实例到原型中,这样则父类的属性继承了两份,一份在实例中,一份在原型中,由于属性的搜索顺序,这样修改子类实例的属性值不会修改原型中的,因此是正确的属性继承。而方法只继承了一份,在原型的__proto__指向的父类原型propotype中。如:
JS中也可以自己设计引用类型!
创建对象
(1)工厂模式:
function createPerson(name,age) { var o = new Object(); o.name = name; o.age = age; o.showName = function() {alert(this.name);}; return o; } var person1 = createPerson("Alen",21);这个模式的问题是无法识别person1的类型,只能用typeof测出为Object类型的。
(2)构造函数模式
function Person(name,age) { this.name = name; this.age = age; this.showName = function() {alert(this.name);}; } var person1 = new Person("Alen",21); alert(typeof person1); //"Person"这里的new做了下面四件事:首先创建一个空Object,然后将构造函数的作用域赋给新对象,然后执行构造函数,然后返回新对象。这本质上原理其实是,任何对象都有一个protoype属性,这个东西指向一个Propotype节点,里面一般包含对象的通用方法。这里每当创建的是函数对象时,就会自动在函数对象propotype节点中加一个constructor属性,指向propotype属性所在的函数。
当用构造函数创建一个实例之后(即new Constructor() ),会在返回的实例中自动添加一个__proto__属性,指向其构造函数的propotype属性。如图:
所以其实是靠constructor这些来进行类型识别的。使用构造函数模式的缺点是,每个方法都要在一个实例中创建一遍!可以用一下代码使方法公用:
function showName() { alert(this.name); } function Person(name,age) { this.name = name; this.age = age; this.showName = showName; }这样需要创建很多的全局函数来当做实例的Person的方法,很不好。
(3)原型模式
原型模式即将属性和方法放在propotype而不是实例中,这样由于所有的Person的实例都指向同一个propotype,所以可以共享属性和方法。
//创建空的构造函数,这样里面只有propotype function Person() { } //为propotype添加属性和方法 Person.propotype.name = "Alen"; Person.propotype.age = 21; Person.propotype.showName = function() { alert(this.name); }; //创建Person实例 var person1 = new Person(); person1.showName(); //Alen这样的缺点,一个是不能初始化构造实例,只能默认值。另一个是很零散。
Person.propotype = { name:"Alen", age:21, showName: function() {alert(this.name);}; }但这样相当于重新定义propotype对象,里面的constructor指针属性会丢失。可以在里面加一个constructor: Person。缺点还是有,最大的问题是原型模式共享的本性。实例间共享属性和方法。
共享基本类型的属性不是问题,当person.name="Ben"这样重新设置属性的时候,会在实例对象中重新加一个name属性,同时不修改propotype中的name属性,以后访问person.name根据原型链,会先在实例中找name属性,找不到才去propotype中找。这样就保证了每个实例的基本类型属性的独立。但是引用类型的属性,在修改时不会在实例中重建,所以原型模式有问题。
(4)组合原型模式和构造函数模式
将方法放在原型中,将属性放在构造函数中:
function Person(name,age) { this.name = name; this.age = age; } Person.propotype.showName = function() { alert(this.name); }; var person1 = new Person("Alen",21); /*或者*/ function Person(name,age) { this.name = name; this.age = age; //一次判断,即可用于所有方法 if(typeof this.showName != "function") { Person.propotype.showName = function() { alert(this.name); }; } }
继承
(1)原型链
当把一个类的构造函数的propotype属性赋值为另一种类的实例对象时,就实现了继承。
如图,当把SubType的propotype设为:
function SuperType() { this.property = true; } SuperType.propotype.getSuperValue = function() { return this.property; }; function SubType() { this.subproperty = false; } SubType.propotype = new SuperType(); //注意一定不能在继承之前添加方法,否则会被继承重置 SubType.propotype.getSubValue = function() {return this.subproperty;}; var instance = new SubType();<pre>
那么可以在图中看到,继承之后,instance的propotype中有SuperType实例应有的getSuperValue方法,__proto__属性。就这样,通过__proto__指针形成一个原型链,实现继承关系。那么问题来了,由于会把实例整个赋值给propotype,因此propotype中会包含属性(严重的问题在于引用类型的属性)。
(2)借用构造函数
function SuperType() { this.color = ["red" , "blue" , "black"]; } /*用子类的作用域调用父类的构造函数,则可继承父类属性*/ function SubType() { SuperType.call(this); }
(3)组合继承
将父类属性先用借用构造函数的方法继承到实例中来,再用原型链复制父类实例到原型中,这样则父类的属性继承了两份,一份在实例中,一份在原型中,由于属性的搜索顺序,这样修改子类实例的属性值不会修改原型中的,因此是正确的属性继承。而方法只继承了一份,在原型的__proto__指向的父类原型propotype中。如:
/*父类*/ function SuperType(name) { this.name = name; } SuperType.propotype.showName = function() { alert(this.name); }; /*子类*/ function SubType(age) { SuperType.call(this,"Alen"); } SubType.propotype = new SuperType(); SubType.propotype.showAge = function() { alert(this.age); };
相关文章推荐
- JQuery1——基础($对象,选择器,对象转换)
- Android学习笔记(二九):嵌入浏览器
- Android java 与 javascript互访(相互调用)的方法例子
- Python动态类型的学习---引用的理解
- Extjs4.0 最新最全视频教程
- Javascript中toFixed方法的改进
- JavaScript演示排序算法
- javascript实现10进制转为N进制数
- 5个常见可用性错误和解决方案
- 2019年开发人员应该学习的8个JavaScript框架
- HTML中的script标签研究
- 异步流程控制:7 行代码学会 co 模块
- JavaScript拆分字符串时产生空字符的原因
- IE8开发人员工具教程(二)
- 土人系列AS入门教程 -- 对象篇
- 在flex中执行一个javascript方法的简单方式
- Flex结合JavaScript读取本地路径的方法
- js可突破windows弹退效果代码
- PostgreSQL教程(三):表的继承和分区表详解