javascript面向对象的敞亮及简便的亲自去做,Jav
分类:pc28.am

重新认识面向对象为了说明 JavaScript 是一门彻底的面向对象的语言,首先有必要从面向对象的概念着手 , 探讨一下面向对象中的几个概念:

javascript面向对象的理解及简单的示例

一切事物皆对象 对象具有封装和继承特性 对象与对象之间使用消息通信,各自存在信息隐藏

零.本节重点:

以这三点做为依据,C 是半面向对象半面向过程语言,因为,虽然他实现了类的封装、继承和多态,但存在非对象性质的全局函数和变量。Java、C# 是完全的面向对象语言,它们通过类的形式组织函数和变量,使之不能脱离对象存在。但这里函数本身是一个过程,只是依附在某个类上。

1.封装:

然而,面向对象仅仅是一个概念或者编程思想而已,它不应该依赖于某个语言存在。比如 Java 采用面向对象思想构造其语言,它实现了类、继承、派生、多态、接口等机制。但是这些机制,只是实现面向对象编程的一种手段,而非必须。换言之,一门语言可以根据其自身特性选择合适的方式来实现面向对象。所以,由于大多数程序员首先学习或者使用的是类似 Java、C 等高级编译型语言(Java 虽然是半编译半解释,但一般做为编译型来讲解),因而先入为主地接受了“类”这个面向对象实现方式,从而在学习脚本语言的时候,习惯性地用类式面向对象语言中的概念来判断该语言是否是面向对象语言,或者是否具备面向对象特性。这也是阻碍程序员深入学习并掌握 JavaScript 的重要原因之一。实际上,JavaScript 语言是通过一种叫做 原型的方式来实现面向对象编程的。下面就来讨论 基于类的面向对象和 基于原型的 面向对象这两种方式在构造客观世界的方式上的差别。基于类的面向对象和基于原型的面向对象方式比较在基于类的面向对象方式中,对象来产生。而在基于原型的面向对象方式中,对象则是依靠 构造器利用 原型构造出来的。举个客观世界的例子来说明二种方式认知的差异。例如工厂造一辆车,一方面,工人必须参照一张工程图纸,设计规定这辆车应该如何制造。这里的工程图纸就好比是语言中的 类 ,而车就是按照这个 类制造出来的;另一方面,工人和机器 利用各种零部件如发动机,轮胎,方向盘 ( 相当于 prototype 的各个属性 ) 将汽车构造出来。事实上关于这两种方式谁更为彻底地表达了面向对象的思想,目前尚有争论。但笔者认为原型式面向对象是一种更为彻底的面向对象方式,理由如下:首先,客观世界中的对象的产生都是其它实物对象构造的结果,而抽象的“图纸”是不能产生“汽车”的,也就是说,类是一个抽象概念而并非实体,而对象的产生是一个实体的产生;其次,按照一切事物皆对象这个最基本的面向对象的法则来看,类 本身并不是一个对象,然而原型方式中的构造器 和原型 本身也是其他对象通过原型方式构造出来的对象。再次,在类式面向对象语言中,对象的状态 由对象实例 所持有,对象的行为方法 则由声明该对象的类所持有,并且只有对象的结构和方法能够被继承;而在原型式面向对象语言中,对象的行为、状态都属于对象本身,并且能够一起被继承,这也更贴近客观实际。最后,类式面向对象语言比如 Java,为了弥补无法使用面向过程语言中全局函数和变量的不便,允许在类中声明静态 属性和静态方法。而实际上,客观世界不存在所谓静态概念,因为一切事物皆对象!而在原型式面向对象语言中,除内建对象 外,不允许全局对象、方法或者属性的存在,也没有静态概念。所有语言元素 必须依赖对象存在。但由于函数式语言的特点,语言元素所依赖的对象是随着运行时 上下文 变化而变化的,具体体现在 this 指针的变化。正是这种特点更贴近 “万物皆有所属,宇宙乃万物生存之根本”的自然观点。

 

JavaScript 面向对象基础知识

2.继承:

虽然 JavaScript 本身是没有类的概念,但它仍然有面向对象的特性,虽然和一般常见的面向对象语言有所差异。

 

简单的创建一个对象的方法如下:

壹.下面理解:

function myObject() {};JavaScript 中创建对象的方法一般来说有两种:函数构造法和字面量法,上面这种属函数构造法。下面是一个字面量法的例子:var myObject = {};

一. javascript面向对象概念:

如果仅仅需要一个对象,而不需要对象的其它实例的情况下,推荐用字面量法。如果需要对象的多个实例,则推荐函数构造法。定义属性和方法

为了说明 JavaScript 是一门彻底的面向对象的语言,首先有必要从面向对象的概念着手 , 探讨一下面向对象中的几个概念:

function myObject() { this.iAm = 'an object'; this.whatAmI = function() { console.log; };};

var myObject = { iAm : 'an object', whatAmI : function() { console.log; }};

    1.一切事物皆对象

以上两种方法创建的对象中,都有一个名为 “iAm” 的属性,还有一个名为 “whatAmI” 的方法。属性是对象中的变量,方法则是对象中的函数。

    2.对象具有封装和继承特性

如何获取属性及调用方法:

    3.对象与对象之间使用消息通信,各自存在信息隐藏

var w = myObject.iAm;myObject.whatAmI();

以这三点做为依据,C 是半面向对象半面向过程语言,因为,虽然他实现了类的封装、继承和多态,但存在非对象性质的全局函数和变量。Java、C# 是完全的面向对象语言,它们通过类的形式组织函数和变量,使之不能脱离对象存在。但这里函数本身是一个过程,只是依附在某个类上。

调用方法的时候后面一定要加上括号,如果不加括号,那么它只是返回方法的引用而已。两种创建对象方法的区别

javascript面向对象的敞亮及简便的亲自去做,JavaScript的面向对象编程底蕴_底工知识_脚本之家。然而,面向对象仅仅是一个概念或者编程思想而已,它不应该依赖于某个语言存在。比如 Java 采用面向对象思想构造其语言,它实现了类、继承、派生、多态、接口等机制。但是这些机制,只是实现面向对象编程的一种手段,而非必须。换言之,一门语言可以根据其自身特性选择合适的方式来实现面向对象。所以,由于大多数程序员首先学习或者使用的是类似 Java、C 等高级编译型语言(Java 虽然是半编译半解释,但一般做为编译型来讲解),因而先入为主地接受了“类”这个面向对象实现方式,从而在学习脚本语言的时候,习惯性地用类式面向对象语言中的概念来判断该语言是否是面向对象语言,或者是否具备面向对象特性。这也是阻碍程序员深入学习并掌握 JavaScript 的重要原因之一。

函数构造法里面定义属性和方法的时候,都要用前缀 this,字面量法不需要。 函数构造法给属性和方法赋值的时候用的是 =,字面量法用的是 : 。 如果有多个属性或方法,函数构造法里面用 ; 隔开,字面量法用 , 隔开。

实际上,JavaScript 语言是通过一种叫做 原型(prototype)的方式来实现面向对象编程的。下面就来讨论 基于类的(class-based)面向对象基于原型的 (prototype-based) 面向对象这两种方式在构造客观世界的方式上的差别。

对于字面量法创建的对象,可以直接用对象的引用调用其属性或方法:

二.基于类的面向对象和基于原型的面向对象方式比较:

myObject.whatAmI();

在基于类的面向对象方式中,对象(object)依靠 类(class)来产生。而在基于原型的面向对象方式中,对象(object)则是依靠 构造器(constructor)利用 原型(prototype)构造出来的。举个客观世界的例子来说明二种方式认知的差异。例如工厂造一辆车,一方面,工人必须参照一张工程图纸,设计规定这辆车应该如何制造。这里的工程图纸就好比是语言中的 类 (class),而车就是按照这个 类(class)制造出来的;另一方面,工人和机器 ( 相当于 constructor) 利用各种零部件如发动机,轮胎,方向盘 ( 相当于 prototype 的各个属性 ) 将汽车构造出来。

而对于函数构造法而言,需要创建对象的实例,才能调用其属性或方法:

事实上关于这两种方式谁更为彻底地表达了面向对象的思想,目前尚有争论。但笔者认为原型式面向对象是一种更为彻底的面向对象方式,理由如下:

var myNewObject = new myObject();myNewObject.whatAmI();

首先,客观世界中的对象的产生都是其它实物对象构造的结果,而抽象的“图纸”是不能产生“汽车”的,也就是说,类是一个抽象概念而并非实体,而对象的产生是一个实体的产生;

使用构造函数

其次,按照一切事物皆对象这个最基本的面向对象的法则来看,类 (class) 本身并不是一个对象,然而原型方式中的构造器 (constructor) 和原型 (prototype) 本身也是其他对象通过原型方式构造出来的对象。

现在再来回归一下之前的函数构造法:

再次,在类式面向对象语言中,对象的状态 (state) 由对象实例 (instance) 所持有,对象的行为方法 (method) 则由声明该对象的类所持有,并且只有对象的结构和方法能够被继承;而在原型式面向对象语言中,对象的行为、状态都属于对象本身,并且能够一起被继承(参考资源),这也更贴近客观实际。

function myObject() { this.iAm = 'an object'; this.whatAmI = function() { console.log; };};

最后,类式面向对象语言比如 Java,为了弥补无法使用面向过程语言中全局函数和变量的不便,允许在类中声明静态 (static) 属性和静态方法。而实际上,客观世界不存在所谓静态概念,因为一切事物皆对象!而在原型式面向对象语言中,除内建对象 (build-in object) 外,不允许全局对象、方法或者属性的存在,也没有静态概念。所有语言元素 (primitive) 必须依赖对象存在。但由于函数式语言的特点,语言元素所依赖的对象是随着运行时 (runtime) 上下文 (context) 变化而变化的,具体体现在 this 指针的变化。正是这种特点更贴近 “万物皆有所属,宇宙乃万物生存之根本”的自然观点。在 程序清单 1中 window 便类似与宇宙的概念。

其实它看起来就是个函数,既然是函数,能不能给它传参数呢?将代码再稍作修改:

对象的上下文依赖:

function myObject { this.iAm = what; this.whatAmI = function { console.log('I am '   this.iAm   ' of the '   language   ' language'); };};
 var str = "我是一个 String 对象 , 我声明在这里 , 但我不是独立存在的!"
var obj = { des: "我是一个 Object 对象 , 我声明在这里,我也不是独立存在的。" }; 
var fun = function() { 
    console.log( "我是一个 Function 对象!谁调用我,我属于谁:", this ); 
 }; 

 obj.fun = fun; 

 console.log( this === window );     // 打印 true 
 console.log( window.str === str );  // 打印 true 
 console.log( window.obj === obj );  // 打印 true 
 console.log( window.fun === fun );  // 打印 true 
 fun();                              // 打印 我是一个 Function 对象!谁调用我,我属于谁:window 
 obj.fun();                          // 打印 我是一个 Function 对象!谁调用我,我属于谁:obj 
 fun.apply(str);                   // 打印 我是一个 Function 对象!谁调用我,我属于谁:str 

再将对象实例化,并传入参数:

三.最基本的面向对象:

var myNewObject = new myObject;myNewObject.whatAmI;

字面式 (literal notation) 对象声明:

程序最终输出 I am an object of the JavaScript language。两种创建对象的方法,我该用哪种?

var person = { 
    name: “张三”, 
    age: 26, 
    gender: “男”, 
    eat: function( stuff ) { 
        alert( “我在吃”   stuff ); 
    } 
 }; 
 person.height = 176; 
 delete person[ “age” ];

对于字面量方法而言,因为它不需要实例化,所以如果修改了某对象的值,那么这个对象的值就永久地被修改了,其它任何地方再访问,都是修改后的值。而对于函数构造法而言,修改值的时候是修改其实例的值,它可以实例化 N 个对象出来,每个对象都可以拥有自己不同的值,而且互不干扰。比较以下几段代码。

四.使用函数构造器构造对象:

var myObjectLiteral = { myProperty : 'this is a property'};console.log(myObjectLiteral.myProperty); // log 'this is a property'myObjectLiteral.myProperty = 'this is a new property';console.log(myObjectLiteral.myProperty); // log 'this is a new property'

使用构造器 (constructor) 创建对象:

即便创建了一个新的变量指向这个对象,结果还是一样的:

 // 构造器 Person 本身是一个函数对象
function Person() { 
    // 此处可做一些初始化工作
} 
 // 它有一个名叫 prototype 的属性
Person.prototype = { 
    name: “张三”, 
    age: 26, 
    gender: “男”, 
    eat: function( stuff ) { 
        alert( “我在吃”   stuff ); 
    } 
 } 
 // 使用 new 关键字构造对象
var p = new Person();
var myObjectLiteral = { myProperty : 'this is a property'};console.log(myObjectLiteral.myProperty); // log 'this is a property'var sameObject = myObjectLiteral;myObjectLiteral.myProperty = 'this is a new property';console.log(sameObject.myProperty); // log 'this is a new property'

// 用函数构造法var myObjectConstructor = function() { this.myProperty = 'this is a property'};// 实例化一个对象var constructorOne = new myObjectConstructor();// 实例化第二个对象var constructorTwo = new myObjectConstructor();// 输出console.log(constructorOne.myProperty); // log 'this is a property'// 输出console.log(constructorTwo.myProperty); // log 'this is a property'和预期一样,两个对象的属性值是一样的。如果修个其中一个对象的值呢?// 用函数构造法var myObjectConstructor = function() { this.myProperty = 'this is a property';};// 实例化一个对象var constructorOne = new myObjectConstructor();// 修改对象的属性constructorOne.myProperty = 'this is a new property';// 实例化第二个对象var constructorTwo = new myObjectConstructor();// 输出alert(constructorOne.myProperty); // log 'this is a new property'// 输出alert(constructorTwo.myProperty); // log 'this is a property'

五.彻底理解原型链 (prototype chain):

可以看到,用函数构造法实例化出来的不同对象,相互是独立的,可以各自拥有不同的值。所以说,到底用哪种方法来创建对象,需取决于各自实际情况。

对象的 __proto__ 属性和隐式引用:

function Person( name ) { 
    this.name = name; 
 } 
var p = new Person(); 
// 对象的隐式引用指向了构造器的 prototype 属性,所以此处打印 true 
 console.log( p.__proto__ === Person.prototype ); 

// 原型本身是一个 Object 对象,所以他的隐式引用指向了
// Object 构造器的 prototype 属性 , 故而打印 true 
 console.log( Person.prototype.__proto__ === Object.prototype ); 

// 构造器 Person 本身是一个函数对象,所以此处打印 true 
 console.log( Person.__proto__ === Function.prototype );

六.彻底理解原型链 (prototype chain):

利用原型链 Horse->Mammal->Animal 实现继承:

// 声明 Animal 对象构造器
 function Animal() { 
 } 
 // 将 Animal 的 prototype 属性指向一个对象,
 // 亦可直接理解为指定 Animal 对象的原型
 Animal.prototype = { 
    name: "animal", 
    weight: 0, 
    eat: function() { 
        alert( "Animal is eating!" ); 
    } 
 } 
 // 声明 Mammal 对象构造器
 function Mammal() { 
    this.name = "mammal"; 
 } 
 // 指定 Mammal 对象的原型为一个 Animal 对象。
 // 实际上此处便是在创建 Mammal 对象和 Animal 对象之间的原型链
 Mammal.prototype = new Animal(); 

 // 声明 Horse 对象构造器
 function Horse( height, weight ) { 
    this.name = "horse"; 
    this.height = height; 
    this.weight = weight; 
 } 
 // 将 Horse 对象的原型指定为一个 Mamal 对象,继续构建 Horse 与 Mammal 之间的原型链
 Horse.prototype = new Mammal(); 

 // 重新指定 eat 方法 , 此方法将覆盖从 Animal 原型继承过来的 eat 方法
 Horse.prototype.eat = function() { 
    alert( "Horse is eating grass!" ); 
 } 
 // 验证并理解原型链
 var horse = new Horse( 100, 300 ); 
 console.log( horse.__proto__ === Horse.prototype ); 
 console.log( Horse.prototype.__proto__ === Mammal.prototype ); 
 console.log( Mammal.prototype.__proto__ === Animal.prototype );

 

七.JavaScript 类式继承的实现方法:

使用 Simple Inheritance 实现类式继承:

// 声明 Person 类
var Person = Class.extend( { 
    _issleeping: true, 
    init: function( name ) { 
        this._name = name; 
    }, 
    isSleeping: function() { 
        return this._issleeping; 
    } 
 } ); 
 // 声明 Programmer 类,并继承 Person 
 var Programmer = Person.extend( { 
    init: function( name, issleeping ) { 
        // 调用父类构造函数
        this._super( name ); 
        // 设置自己的状态
        this._issleeping = issleeping; 
    } 
 } ); 
 var person = new Person( "张三" ); 
var diors = new Programmer( "张江男", false ); 
 // 打印 true 
 console.log( person.isSleeping() ); 
 // 打印 false 
 console.log( diors.isSleeping() ); 
 // 此处全为 true,故打印 true 
 console.log( person instanceof Person && person instanceof Class 
    && diors instanceof Programmer && 
    diors instanceof Person && diors instanceof Class );

八.JavaScript 私有成员实现:

使用闭包实现信息隐藏:

// 声明 User 构造器
function User( pwd ) { 
    // 定义私有属性
    var password = pwd; 
    // 定义私有方法 
    function getPassword() { 
        // 返回了闭包中的 password 
        return password; 
    } 
    // 特权函数声明,用于该对象其他公有方法能通过该特权方法访问到私有成员
    this.passwordService = function() { 
        return getPassword(); 
    } 
 } 
 // 公有成员声明
User.prototype.checkPassword = function( pwd ) { 
    return this.passwordService() === pwd; 
 }; 
 // 验证隐藏性
var u = new User( "123456" ); 
 // 打印 true 
 console.log( u.checkPassword( "123456" ) ); 
 // 打印 undefined 
 console.log( u.password ); 
 // 打印 true 
 console.log( typeof u.gePassword === "undefined" );

 

参考:   使用面向对象的技术创建高级 Web 应用程序

 

本文由pc28.am发布于pc28.am,转载请注明出处:javascript面向对象的敞亮及简便的亲自去做,Jav

上一篇:初学者必看的Ajax总结篇,jquery中ajax参数详解 下一篇:没有了
猜你喜欢
热门排行
精彩图文