JavaScript之OOP编程

定义一个对象的最简单的方法

var car = {
		color:"red",
		drive:function() {
			alert(this.color + " car moved");
		}
}

这个方法不是在非常有用,因为它创建了一个单独的对象,而这个对象和任何常见的数据结构没有任何联系,为了创建第二个car实例,必须重新定义它的结构.

通过构造函数创建一个新对象

function Car() {
	this.color = "red";
	this.drive = function(){
		alert(this.color + " car moved");
	}
}
var car = new Car();
car.drive();

JavaScript中的每个函数都有一个称为prototype的属性.如果某个函数被用作构造函数,则这个属性会被自动通过new调用创建对象的原型

function Car() {
	this.color = "red";
}

Car.prototype.drive = function(){
	alert(this.color + " car moved");
}

var car = new Car();
car.drive();

对prototype属性所做的任何更改能够应用于通过new Car()构造的每一个对象,不管它是在更改之前还是更改后创建.为Car.prototype 添加新函数.对于共享相同原型的每一个对象,该函数都可以立即使用,无论它是在更改之前或是之后构造,具体如下:

// 更新原型
function Car(color) {
	this.color = color;
}

Car.prototype.drive = function(){
	alert(this.color + " car is driving");
}

var car1 = new Car("red");
alert(car1.__proto__ === Car.prototype); // true
car1.drive();

// 为原型添加新的函数
Car.prototype.stop = function()	{
	alert(this.color + " car has stopped");
}

var car2 = new Car("blue");

// 共享同一对象原型的对象
alert(Object.getPrototypeOf(car1) === Object.getPrototypeOf(car2));  // true

// 这两个对象现在都能访问这个新的方法
car2.stop();
car1.stop();

面向对象的很重要一个特性就是继承了,这里只要介绍通过原型链继承

// 继承的基本设置
function Car(color) {
	this.color = color;
}

Car.prototype.drive = function(){
	alert(this.color + " car is driving");
}

Car.prototype.turn = function(direction) {
	alert(this.color + " car turns " + direction);
}

Car.prototype.stop = function() {
	alert(this.color + " car has stopped");
}

// 消防车
function FirTruck() {}

FirTruck.prototype.turnCannon = function(direction) {
	alert("Cannon moves to the " + direction);
}

var truck = new FirTruck();
// 因为Car.prototype 并不在truck对象的原型链中
// 因此方法move()并不可用
truck.move();
truck.turnCannon("right");

JavaScript中有一个很特殊的Object.create(proto, properties)方法, 注:IE8及以下不支持

它可以用来创建一个新的空白对象并将其原型设置为proto

function Car(color) {
	this.color = color;
}

Car.prototype.move = function(){
	alert(this.color + " car is driving");
}

Car.prototype.turn = function(direction) {
	alert(this.color + " car turns " + direction);
}

Car.prototype.stop = function() {
	alert(this.color + " car has stopped");
}
if(!Object.create){
        // 兼容性处理
        FireTruck.prototype = Car.prototype;
}else{
	FireTruck.prototype = Object.create(Car.prototype);
}

function FireTruck() {}

// 检查,以防万一
//alert(Object.getPrototypeOf(FireTruck.prototype) === Car.prototype);
// 如果为true
// 则Car.prototype被添加到链中

FireTruck.prototype.turnCannon = function(direction){
	alert("Cannon moves to the " + direction);
}

var truck = new FireTruck();
// 现在可以工作了,因为Car.prototype已经在truck对象的原型链中
truck.move();
truck.turnCannon("right");

代码可以运行,但其输出还是存在一些问题

true

undefined car is driving

Cannon moves to the right

小汽车的color现在可以通过Car的构造函数进行设置.构造函数本身没有执行,所以其color显示为undefined.这个问题很好解决,修改FireTruck构造函数,在其中添加对Car构造函数的调用,这样Car就可以初始化它自己的对象变量

function FireTruck() {
	Car.call(this, "red");
}

再次运行这段代码,欣赏一下正确的输出

即使该代码能够成功运行,但仍有一个小问题需要解决.当这个新函数创建时,它的prototype属性并不为空.它有一个称为constructor的属性将引用函数本身,当调用

FireTruck.prototype = Object.create(Car.prototype);

时,该属性丢失,因为这个新建的对象并不具有自己的属性.可以将丢失的属性作为第二个参数传递给create

FireTruck.prototype = Object.create(Car.prototype, {
		constructor: {
			value: FireTruck,         // 和FireTruck.prototype.constructor一样
			enumerable: false,
			writable: true,
			configurable: true
		}
	});

这里的constructor并不是通常的属性.当对象的键值进行循环时,它不会出现,但可以通过名称直接访问.通过给create()的第二个参数传递属性"描述符"可以取得相同的效果

描述符具有如下所示的几个字段

value: 初始值

enumerable: 如果属性显示在对象属性的列表中, 在像for...in 这样的循环或Object.keys中

writable: 如果属性可以被指派一个不同的值

configurable: 如果描述符定义的规则可以被修改或其属性可以删除,则为true

这样就可以模仿真实的 constructor 的行为

 最终版本的的继承示例

function extend(subConstructor, superConstructor) {
	if(!Object.create){
		subConstructor.prototype = superConstructor.prototype;
		subConstructor.constructor = {
				value: FireTruck,         // 和FireTruck.prototype.constructor一样
				enumerable: false,
				writable: true,
				configurable: true
			}
	}else{
		subConstructor.prototype = Object.create(superConstructor.prototype, {
			constructor: {
				value: FireTruck,         // 和FireTruck.prototype.constructor一样
				enumerable: false,
				writable: true,
				configurable: true
			}
		});
	}
}

function Car(color) {
	this.color = color;
}

Car.prototype.move = function(){
	alert(this.color + " car is driving");
}

Car.prototype.turn = function(direction) {
	alert(this.color + " car turns " + direction);
}

Car.prototype.stop = function() {
	alert(this.color + " car has stopped");
}

function FireTruck() {
	Car.call(this, "red");
}

extend(FireTruck, Car);

FireTruck.prototype.turnCannon = function(direction){
	alert("Cannon moves to the " + direction);
}

var truck = new FireTruck();
truck.move();
truck.turnCannon("right");
时间: 2024-10-08 12:37:31

JavaScript之OOP编程的相关文章

JavaScript的OOP编程1

首先要说的是,javascript其实是可以进行OOP编程的,其次javascript的OOP编程实现方式有多种,我写的这一种只是我测试过,可行的一种 version1 // 父类 function Person(name){this.name = name} Person.prototype.say = saymyname; function saymyname(){alert(this.name)} // 子类 function Employee(name){Person.call(this

javascript实现OOP编程

1.首先通过一个函数来实现JS的单继承.使用原型方式来实现继承 1 (function () { 2 3 $.extend({ 4 oop: { 5 extend: function (child, father) { 6 if (father == null) { 7 var father = function () { }; 8 console.log(this); 9 father.prototype = this 10 } 11 child.prototype = new father(

JavaScript的OOP编程2

我做了一个observer的设计模式实现 version1 // -------------------------------------------------- function Subject(){} Subject.prototype.add = function(obj) { if(typeof(obj.update) === "function") { this.objects.push(obj); return true; } return false; } Subje

JavaScript的面向对象编程(OOP)(一)——类

在学习JavaScript面向对象的编程之前,需要知道,并了解面向对象的一些基本的常识.初学者中大多数都以为面向对象中,面向对象的编程是很重要和占据很大一部分精力.笔者在之前也是认为OOP是面向对象的主要部分,那么和我持有一样想法的,下面先要纠正这一想法,真正了解面向对象. 一.初识面向对象 面向对象分为三部分,包括面向对象分析(OOA).面向对象设计(OOD).面向对象的程序设计(OOP). 1.1 OO编程(Object Oriented Analysis) 典型的OO编程过程,应先整理需求

javascript oop编程 — 实现继承的三种形式

javascript  oop编程  - 实现继承的三种形式[1] (1)模拟类的方式, 我们都知道js是原型继承机制,不存在class和instance分离的这种方式 假设,我们有两个类 function  Animal(){ this.name = "animal"; this.eat = function(){ consle.log("eating"); } } function Cat(){ this.say = function(){ console.lo

Lua下通过元表模拟OOP编程,继承多态

Lua本身是没有以明确的定义来支持OOP编程的,但是我们却可以通过Lua内核提供的一些特性来间接实现简单的面向对象的编程. 通过Lua中的 table结构  metatable 以及函数可以配合实现OOP,以及继承.这些说白了都是一种伪实现,不建议在Lua下使用多重继承 . 在LUA中你想要 强制实现OOP 你必须需要懂一下几个关键词!! 什么是语法糖? 语法糖即糖衣语法,C/C++升级过程中的面向对象 整体就是一种语法糖 ,是由英国计算机科学家彼得·约翰·兰达(Peter J. Landin)

JavaScript 表单编程

目标:主要是访问用户输入的表单数据,校验用户输入的正确性. 获取表单的引用: //方法一:将表单的ID作为方法的参数 var f1 = document.getElementById("f1"); //方法二:表单集合,得到第一个表单 var f2 = document.forms[0]; //方法三:得到名为fm的表单 var f3 = document.forms["fm"]; //方法四:简写 var f4 = document.fm 访问表单的元素: //获

【OOP编程思想小感悟】

写点啥...开头省略1000字,哈哈,开始讨论OOP编程思想啦~ 我来翻译一下OOP吧(面向对象编程) 最近一直在看C++的一本书,看到书中有这样一句话(我按我的意思概括一下哈):OOP是一种编程思想,和具体的编程语言无关.(这是真的么?) 我们继续说哈,话说我也已经工作快三年了,不过一直在做运维方面的工作(其实我不太喜欢,太麻烦),所以在技术方面略显木讷.(不说闲话了) 大学期间和我看到这句话期间(可能之前也看过,但是一直不明白什么意思),我一直听到这样一种观点:C语言是面向过程的编程语言,C

PHP面向对象(OOP)编程完全教程

转自:http://blog.snsgou.com/post-41.html 面向对象编程(OOP)是我们编程的一项基本技能,PHP5对OOP提供了良好的支持.如何使用OOP的思想来进行PHP的高级编程,对于提高PHP编程能力和规划好Web开发构架都是非常有意义的.下面我们就通过实例来说明使用PHP的OOP进行编程的实际意义和应用方法. 我们通常在做一个有数据库后台的网站的时候,都会考虑到程序需要适用于不同的应用环境.和其他编程语言有所不同的是,在PHP中,操作数据库的是一系列的具体功能函数(如