JavaScript 面向对象学习——2

继承是面向对象的特性(封装、抽象、继承、多态)之一,JavaScript作为面向对象语言自然拥有继承的特性。如果想要真正理解JavaScript的继承机制,那么应该从JavaScript对象的原型说起。

    1 prototype

每一个对象都有一个原型属性,当然,不同的浏览器对这个属性包装不一样。比如我们使用 Firefox 或者 Google浏览器就能通过 __proto__ 获取属性指向的实例引用(原型对象)。IE浏览器不能通过以上方法获取,并不能说明这个对象不存在!我们知道JavaScript中函数也是一个对象,一个Function对象,既然是对象他也有原型对象的引用,他的属性名称就是prototype,换句话:我们能够通过函数调用prototype的方式获取原型引用。函数又可以称作为类,那么类的实例所拥有的原型引用与函数本身所拥有的原型引用是完全相同的,这就保证了原型共享,为继承打好了基础。

    总结:

1)每个函数都有一个prototype(原型)属性,这个属性是一个对象,它的用途是包含所有实例共享的属性和方法。逻辑上可以这么理解:使用原型的好处可以让所有对象实例共享它所包含的属性和方法,而且函数本身与该函数所有的实例共享一个原型。

2)函数调用原型采用 Class.prototype,实例调用原型属性 obj.__proto__,判断(Class.prototype ==obj.__proto__)

3)原型是一个对象,一个实例化的对象,这个对象的实例化过程比较特殊,特殊之处在于他不是通过类本身去实例化的,但是他又是该类的实例。比如一个类 function Person(name,age){ this.name=name; ....}; var p = new Person(‘learn‘,23);如果p的原型是通过类本身去实例化的话,那么原型一定会有一个name属性,然而实际上原型是一个 Person{ };却不是一个Person的实例,又不是通过Person的构造方法new出来的。可以用 instanceof 测试这个原型不属于Person实例。

function Person(name ,age){
  this.name = name;
  this.age = age;
  this.info = function(){
    return this.name + this.age;
  };
}
var p = new Person(‘learn‘,23);
console.info(Person.prototype); // Person{}
console.info(p.__proto__); // Person{}
console.info(Person.prototype == p.__proto__ );//true
console.info(p.__proto__ instanceof Person);//false

  2 constructor

与原型一样,每一个函数都有一个constructor属性,每一个函数的原型也有一个constructor属性,既然原型中有constructor属性,自然每一个对象实例就能共享这个constructor属性。那么这里要注意了:函数其实有两个constructor属性,一个是自身的属性,可以通过 Class.constructor 获取(js属性调用就近原则),一个是原型中的constructor属性,可以通过 Class.prototype.constructor 或者 obj.__proto__.construcotr 获取。这两个是有本质差异的,前者是一个匿名函数的引用,后者是该类本身的引用。而且前者是类专有私有的属性,是不被实例共享的。实际开发中,我们不会去触碰前者,我们往往是在继承的时候对后者进行改变。

    总结:

1)每个函数都有一个类私有的constructor属性和一个原型当中共享的constructor属性

2)只有类本身才能调用这个私有属性:Class.constructor ;原型constructor属性调用:obj.consturctor 或 obj.__proto__.construcotr 或 Class.prototype.constructor

3)类私有的constructor属性指向一个匿名函数的引用,注意是函数引用,不是函数的实例引用;原型的constructor属性则是指向类本身的引用,这里也是函数引用,不是实例引用。

4)原型的constructor属性是一个类的重要标志,他一定要指向类本身,因为面向对象规定构造函数指向本身。然而类的私有constructor属性是由系统决定,我们不最好不要触碰。

console.info(Person.constructor);//Function()
console.info(Person.prototype.constructor);// Person(name, age)
console.info(p.constructor);// Person(name, age)
console.info(p.__proto__.constructor);// Person(name, age)

    3 extend

JavaScript是通过原型进行继承的,原型的作用就是共享,所以通过原型可以很好的达到继承机制。采用原型继承时要注意必不可少的两点:子类的原型必须指向父类的实例,子类原型的constructor属性必须指向子类本身。通过原型指向父类实例,从而所有子类实例共享父类的属性与方法,达到继承效果。通过子类原型的constructor属性指向子类本身,达到面向对象中要求的构造函数指向之间。

    总结:

1)子类的原型指向父类的实例,SubClass.prototype = new SuperClass( );

2)子类的原型构造函数指向子类本身,SubClass.prototype.constructor = SubClass ;

3 ) 由于js使用原型继承,导致构造函数也被继承,然而面向对象来说这是错误的,所以才有第二步重新指向构造函数。

4 ) 个人理解 Person 与 Person.prototype 的差异是:前者是指构造函数或类本身,后者其实是一个所有实例都共享的实例对象。

5)如果单纯只是调用某一个函数那么可以使用 call 函数进行处理,而无需继承。 Class.method.call(Self , param) ;

function extends( SubClass , SuperClass){
/*第一步 : 构建桥梁类Bridge,他的作用就是完全替代父类本身,包括构造方法*/
var Bridge = function( ){ } ;
Bridge.prototype = new SuperClass( ); // Bridge.prototype.constructor = SuperClass ;这一步原型链默认完成 
/*第二步 : 使用子类的原型链继承桥梁父类*/
SubClass.prototype = new Bridge( );  
SubClass.prototype.constructor = SubClass;  
/*第三步 : 扩展子类属性,把父类的引用作为子类的共享属性,为子类中所调用 */
SubClass.prototype.superClass = SuperClass.prototype;       //  这里必须是prototype,而不能是函数本身
/*第四步 : 为保证程序正常运行机制,做个小判断*/
if( SuperClass.prototype.constructor == Object.prototype.constructor  ){
SuperClass.prototype.constructor = SuperClass;
} 
}
6)javascript是单继承的,但如果想在一个类中拥有多个类的方法,那么就要使用聚合(掺元类,把其他类的方法为自己所用)。
具体如下:
function mixin(ReceivingClass,GivingClass){
    for(var method in GivingClass.prototype ){
        if(ReceivingClass.prototype[method] == undefined){
  /* 这里特别注意使用prototype而不使用原因就是 静态属性 与 原型属性的差异 */
            ReceivingClass.prototype[method]= GivingClass.prototype[method];
        }
    }
}
时间: 2024-08-08 01:29:42

JavaScript 面向对象学习——2的相关文章

javascript面向对象学习笔记(二)——创建对象

javascript面向对象学习笔记(二)--创建对象 工厂模式 该模值抽象了创建具体对象de过程.用函数来封装噫特定接口创建对象的细节. function createPerson(name,age,job){ var o=new Object(); o.name=name; o.age=age; o.job=job; o.sayName=function(){ alert(this.name); }; return o; } var person1=createPerson("Chiaki&

JavaScript 面向对象学习——1

公司项目采用Ext,结果本人发现入门不易!尤其是采用JavaScript编写面向对象程序,经常使用jQuery的知道,jQuery是面向函数编程的,所以很容易入门.然而,Ext是面向对象的,那么,当你想要自定义Ext组件的时候,或者使用Ext组件的时候就会很苦恼.所以,要先学习Javascript面向对象基础,其次查看Ext源代码. 这将是后期的学习路线,博客路线. 1 Javascript是基于原型(Prototype based)的面向对象的语言,Java语言,是基于类模式(Class ba

JavaScript面向对象学习——4

对象的创建 1)字面量.2)new.3)Object.create() 属性的访问 1.可以通过点(.)或方括号([」)运算符来获取属性的值.运算符左侧应当是一个表达式,它返回一个对象.对于点(.)来说,右侧必须是一个以属性名称命名的简单标识符.对于方括号来说(「)),方括号内必须是一个计算结果为字符串的表达式,这个字符串就是属性的名字.在ECMAScript 3中,点运算符后的标识符不能是保留字,比如,o.for或o.class是非法的,因为for是JavaScript的关键字,class是保

JavaScript面向对象学习——3

对象基础介绍: 1.对象是JavaScript的基本数据类型.在java中Object是所有对象的基类,在JavaScript中同样,Object是所有对象的基类,那么Object自身属性和方法在所有对象中都会体现,只是不同的类对方法有不同的重写. 2.JavaScript对象是动态的-可以新增属性也可以删除属性-但它们常用来模拟静态对象以及静态类型语言中的"结构体"(struct).有时它们也用做字符串的集合(忽略名/值对中的值). 3.除字符串.数字.true. false. nu

JavaScript面向对象学习笔记

面向对象:变量和属性一样的.属性:属于一个对象变量:属于任何一个人函数:方法:属于一个对象难点:this:当前的方法属于谁,this就是谁的例子window.show = function(){ alert(this);}//this是windowfunction show(){ alert(this);}Object:用来实现对象var obj = new Object();例子:var obj = new Object();obj.name = "zhaobw";obj.age =

Javascript面向对象学习笔记(二)--创建对象(七种模式)

一.工厂模式 考虑到ECMAScript中无法创建类,开发人员就发明了一种函数,用函数来封装以特定接口创建对象的细节 function createPerson(name,age,job){ var o=new Object(); o.name=name; o.age=age; o.job=job; o.sayName=function(){ alert(this.name); }; return o; } var person1=createPerson("小码农",18,"

javascript面向对象学习笔记——创建对象(转)

工厂模式 该模值抽象了创建具体对象de过程.用函数来封装噫特定接口创建对象的细节. function createPerson(name,age,job){ var o=new Object(); o.name=name; o.age=age; o.job=job; o.sayName=function(){ alert(this.name); }; return o; } var person1=createPerson("Chiaki",21,"Software Engi

javascript面向对象学习

1.this指向问题,指向的是当前的方法属于谁,当前的方法属于谁就指向谁!! 例子: oDiv.onclick = function () { this指向的是oDiv,因为这个方法属于oDiv } var obj = new Object();  //构造对象 obj.show=function(){     this====>>这时候的函数属于obj,所以this指向的是obj这个对象 } 2.函数的形式 函数: 方法: 事件处理函数: 构造函数==>函数用来构造对象叫什么构造函数!

JavaScript面向对象-静态方法-私有方法-公有方法-特权方法,学习

var baseClass= function(){ function show(){//私有方法 alert("访问私有方法"); } function showName(){ alert(this.name); } this.showw = function (){//特权方法 showName(); } } //静态方法 baseClass.showStatic = function(){ alert("访问静态方法"); } //公有方法 baseClass