JavaScript 面向对象程序设计详解【类的创建、实例对象、构造函数、原型等】

本文实例讲述了JavaScript 面向对象程序设计。分享给大家供大家参考,具体如下:

类的创建于实例对象

工厂模型创建对象

function CreatePerson ( name,sex,age ) {
 
 var obj = new Object();
 
 obj.name = name;
 obj.sex = sex;
 obj.age = age;
 
 obj.sayName = function () {
  
  console.log( this.name );
  
 }
 
 return obj;
 
}

var p1 = CreatePerson('zf','女',22);

p1.sayName(); //zf

console.log( p1.name ); //zf

构造函数式

//函数的第一个字母大写(类的模板)
function Person ( name,age,sex ) {
 
 this.name = name;
 this.age = age;
 this.sex =sex;
 
 this.sayName = function () {
  
  alert(this.name);
  
 }
 
}

//构造一个对象, 使用new关键字, 传递参数, 执行模板代码, 返回对象。

var p1 = new Person('zf',20,'女'); //类的概念:根据模板创建出不同的实例对象
 
console.log( p1.name );

p1.sayName();

创建类的实例:

  • 当作构造函数去使用

    var p1 = new Person('a1',20);

  • 作为普通函数去调用

    Person('a2',20); //在全局环境中定义属性并赋值, 直接定义在window上。

  • 在另个一对象的作用域中调用

    var o = new Object();
    Person.call(o,'a3',23);

Object每个实例都会具有的属性和方法:

Constructor: 保存着用于创建当前对象的函数。(构造函数)
hasOwnProperty(propertyName):用于检测给定的属性在当前对象实例中(而不是原型中)是否存在。
isPrototypeOf(Object): 用于检查传入的对象是否是另外一个对象的原型。
propertyIsEnumerable(propertyName):用于检查给定的属性是否能够使用for-in语句来枚举。
toLocaleString():返回对象的字符串表示。该字符串与执行环境的地区对应.
toString():返回对象的字符串表示。
valueOf():返回对象的字符串、数值或布尔表示。

判断一个对象是不是另一个对象的实例,通常使用的是 instanceof. 比较少使用constructor。

原型

创建每一个函数的时候,都有一个prototype属性. 这个是属性,是一个指针。而这个对象总是指向一个对象。
这个对象 的用途就是将特定的属性和方法包含在内,是一个实例对象, 起到了一个所有实例所共享的作用。
屏蔽了,构造函数的缺点,new 一个对象,就把构造函数内的方法实例化一次。

function Person () {
    
}

var obj = Person.prototype;

console.log( obj ); //Person.prototype 就是一个对象
//Person.prototype 内部存在指针,指针指向一个对象。 这个对象称之为:原型对象。原型对象,被所有的实例对象所共享。

console.log( obj.constructor ); //function Person(){} //obj这个对象的构造器就是 Person

原型图例:

也不能使用new关键字。

//稳妥构造函数式 durable object (稳妥对象)
//1,没有公共的属性
//2,不能使用this对象

function Person ( name,age ) {
 
 //创建一个要返回的对象。 利用工厂模式思维。
 var obj = new Object();
 
 //可以定义一下是有的变量和函数 private
 
 var name = name || 'zf';
 
//      var sex = '女';
//      var sayName = function () {
//      }

  
 //添加一个对外的方法
 obj.sayName = function () {
  console.log(name);
 }
 
 return obj;
 
}

var p1 = Person('xixi',20);

p1.sayName(); 

深入原型继承的概念

如果让原型对象等于另一个类型的实例,结果会怎么样呢?显然此时的原型对象将包含一个指向另一个原型的指针,相应的另一个原型中也包含着一个指向另一个构造函数的指针。

原型链: 利用原型让一个引用类型继承另外一个引用类型的属性和方法。

构造函数 原型对象 实例对象

  • 构造函数.prototype = 原型对象

  • 原型对象.constructor = 构造函数

  • 实例对象.__proto__ = 原型对象

  • 原型对象.isPrototypeOf(实例对象)

  • 构造函数 实例对象 (类和实例)

isPrototypeOf(); //判断是否 一个对象的 原型


继承的三种方式

原型继承

//原型继承的特点:
//即继承了父类的模板,又继承了父类的原型对象。 (全方位的继承)
//父类
function Person ( name,age ) {
 
 this.name = name;
 this.age = age;
 
}

Person.prototype.id = 10;

//子类
function Boy ( sex ) {
 
 this.sex = sex;  
 
}

//原型继承
Boy.prototype = new Person('zz');

var b = new Boy();

console.log( b.name ); //zz
console.log( b.id ); //10

类继承

类继承 (只继承模板) 不继承原型对象 (借用构造函数的方式继承)

//父类
function Person ( name,age ) {
 
 this.name = name;
 this.age = age;
 
}

Person.prototype.id = 10;

//子类
function Boy ( name,age,sex ) {
 
 //类继承
 Person.call(this,name,age);
 
 this.sex = sex;  
 
}

var b = new Boy('zf',20,'女');

console.log( b.name ); //zf
console.log( b.age ); //20
console.log( b.sex ); //女
console.log( b.id ); //父类的原型对象并没有继承过来.

 

混合继承

原型继承+类继承

 
 //父类  (关联父类和子类的关系)
function Person ( name,age ) {
 
 this.name = name;
 this.age = age;
 
}

Person.prototype.id = 10;
Person.prototype.sayName = function () {
 console.log( this.name );
}

//子类
function Boy ( name,age,sex ) {
 
 //1 类继承
 Person.call(this,name,age); //继承父类的模板
 
 this.sex = sex;  
 
}    

//2 原型继承
//父类的实例 和 父类的 原型对象的关系.
Boy.prototype = new Person(); //继承父类的原型对象

var b = new Boy('z1',20,'女');

console.log( b.name );//z1
console.log( b.sex ); //女
console.log( b.id ); //10

b.sayName(); //z1 

ExtJs底层继承方式

模拟ExtJs底层继承一部分代码

//ExtJs 继承
//2件事: 继承了1次父类的模板,继承了一次父类的原型对象


function Person ( name,age ) {
 
 this.name = name;
 this.age = age;
 
}

Person.prototype = {
 
 constructor: Person,
 
 sayHello: function () {

  console.log('hello world!');

 }
 
}

function Boy ( name,age,sex ) {
 
 //call 绑定父类的模板函数 实现 借用构造函数继承 只复制了父类的模板
 
//    Person.call(this,name,age);

  Boy.superClass.constructor.call(this,name,age);
 
 this.sex = sex;  
 
}

//原型继承的方式: 即继承了父类的模板,又继承了父类的原型对象。
//   Boy.prototype = new Person();
//只继承 父类的原型对象
 extend(Boy,Person); // 目的 只继承 父类的原型对象 , 需要那两个类产生关联关系.

//给子类加了一个原型对象的方法。
Boy.prototype.sayHello = function () {
 
 console.log('hi,js');
 
}

var b = new Boy('zf',20,'男');

console.log( b.name );
console.log( b.sex );
b.sayHello(); 

Boy.superClass.sayHello.call(b);

//extend方法

//sub子类, sup 父类
function extend ( sub,sup ) {
 
 //目的, 实现只继承 父类的原型对象。 从原型对象入手
 
 //1,创建一个空函数, 目的:空函数进行中转
 var F = new Function(); // 用一个空函数进行中转。
 
//    把父类的模板屏蔽掉, 父类的原型取到。
 
 F.prototype = sup.prototype; //2实现空函数的原型对象 和 超类的原型对象转换
 
 sub.prototype = new F(); //3原型继承
 
 //做善后处理。 还原构造器 ,
 sub.prototype.constructor = sub; //4 ,还原子类的构造器
 
//    保存一下父类的原型对象 // 因为 ①方便解耦, 减低耦合性  ② 可以方便获得父类的原型对象
 sub.superClass = sup.prototype; //5 ,保存父类的原型对象。 //自定义一个子类的静态属性 , 接受父类的原型对象。
 
 //判断父类的原型对象的构造器, (防止简单原型中给更改为 Object)
 if ( sup.prototype.constructor == Object.prototype.constructor ) {
  
  sup.prototype.constructor = sup; //还原父类原型对象的构造器
  
 }
 
}

感兴趣的朋友可以使用在线HTML/CSS/JavaScript代码运行工具:http://tools.laike.net/code/HtmlJsRun测试上述代码运行效果。

更多关于JavaScript相关内容感兴趣的读者可查看本站专题:《javascript面向对象入门教程》、《JavaScript错误与调试技巧总结》、《JavaScript数据结构与算法技巧总结》、《JavaScript遍历算法与技巧总结》及《JavaScript数学运算用法总结》

希望本文所述对大家JavaScript程序设计有所帮助。