- 浏览: 51216 次
- 性别:
- 来自: 青岛
文章分类
最新评论
基于对象的JavaScript编程 1
基于对象的JavaScript编程
-JavaScript Object-Oriented Programming
接触ajax一直不是很深入,然后对于JavaScript的所谓基于对象的理解更是肤浅的很,g了很多中文的文章看着一头雾水,找了一篇2001年老外的文章看了看,我*!讲的既简单又涉及到了精髓,忍不住花了两天翻译了一下,这是第一部分,第二部分抽时间也去翻一下,本人英文水平处于"伦敦郊区"水平,大家多喷。-.-
这个可能让你很震惊,但是JavaScript是一种很强大的基于对象(object-based或者prototype-based,随便你怎么称呼)的编程语言。的确如此,JavaScript是一种强大的编程语言,并不是只能制造图片滚动效果和平淡或华丽的展现效果。可是,很少使用者能认识到JavaScript潜在的强大的功能。如果你恰恰属于这个行列,那这篇文章正好适合你。
首先,JavaScript跟java一样不是一门纯粹的OOP(Object-Oriented-Programming)语言,但是它是一门基于对象的编程语言。但是,你为什么要用JavaScript的对象呢?原因是这样你不仅能熟悉JavaScript的工作原理,而且在编写脚本时,你还可以自己创建JavaScript对象,而不总是像你现在这样只编写一些顺序执行的代码。这些编写的JavaScript对象你也可以在以后重复利用。
我希望这篇文章能够促成那些渴望学习面向对象技术的中级JavaScript工程师形成对JavaScript面向对象世界的持续兴趣,从而成为专家。
在这篇导读里,你能学到:
JavaScript的基本数据类型(JavaScript's primitive data types )
在JavaScript中什么是对象(What an object is in JavaScript )
怎样创建一个普通的对象(How to create custom objects )
构造器是什么(What a constructor is )
对象的基本属性是什么(What an object's prototype property is )
JavaScript的基本数据类型
JavaScript有五种基本数据类型:
Undefined,
Null,
Boolean,
Number,
String。
在这篇导读中,我们会大量的用到后面三种类型
Boolean 类型是一种包含或者true或者false两种值的逻辑实体。例如:
var BooleanValue = true;
Number类型是一种用来描述数的大小的一组数值。例如:
var NumericalValue = 354;
String 类型是一组包含零到多个字符的类型。例如:
var StringValue = "This is a String";
Typeof
typeof 是JavaScript中一个常用的操作符。它能告诉你正在操作的数据的类型。这有意义吗?让我们来看几个例子:
var BooleanValue = true;
var NumericalValue = 354;
var StringValue = "This is a String";
alert(typeof BooleanValue) // 显示 "boolean"
alert(typeof NumericalValue) // 显示 "number"
alert(typeof StringValue) // 显示 "string"
对象
对象是属性的集合。这些属性可以是基本数据类型,其他的对象或者是函数(这里先暂时称为方法,后面会有别的名称)。构造函数(简单说是构造器)是一种用来创建一个对象的方法——这个我们会在后面详细讨论。JavaScript有许多内置的对象,如:Array, Image, 和Date对象。你们很多人都很熟悉怎样使用Image对象来构建华丽的滚动效果。那么,当你使用这些代码:
var Image1 = new Image();
Image1.src = "myDog.gif";
事实上你已经创建了一个Image对象,并且给你自己的 Image对象设置了一个属性值:src属性。Image1是一个新的Image对象;换句话说,它是一个Image类型的实例。使用JavaScript中的‘.’符号,上面代码就取得了你自己的image对象的src属性并设置了它的值。现在,我们来学习怎么创建自己的对象:
function myFunc(){
}
var myObject = new myFunc();
alert(typeof myObject); // 显示 "object"
我们刚刚创建了自己的对象。事实上我们已经构建了一个myFunc对象的实例,myFunc()是一个构造方法;构造方法指出了该对象在被创建时要进行的初始化工作,尽管我们这个构造方法里没有什么初始化的工作(原文:it lays out the blueprint from which objects that are created from it will follow (although, in this case, it doesn't lay out much of a blueprint).)。这样,JavaScript是怎样知道要创建一个myFunc的对象,而不是返回这个方法的返回值的呢?让我们来比较一下上面的例子和下面这个,一般方法更经常的用法:
function myFunc(){
return 5;
}
var myObject = myFunc();
alert(typeof myObject); // 显示 "number"
当前的这个例子里,我们把5赋值给了myObject,这样,这两段脚本的区别在哪呢?答案:new关键字。就是它告诉了JavaScript的编译器遵循myFunc()构造方法中设置的初始化内容创建了一个对象。事实上,当我们创建了一个Image对象,我们也进行了相同的过程,只不过这里用了自己的构造方法而已,而在创建Image对象是用了JavaScript内置的Image()构造方法。
到目前为止,我们已经学习了怎样建一个构造函数,怎样用这个构造函数去构建一个对象实例。在我们的例子里,我们创建了一个myFunc()构造器,并且创建了一个myFunc对象的实例,并把它赋给了变量myObject。
这些都很好很强大,但是什么才是关键呢?是的,就像我们给Image对象添加属性那样,myObject也可以被分配各种各样的属性:
function myFunc(){
}
var myObject = new myFunc();
myObject.StringValue = "This is a String";
alert(myObject.StringValue); // 显示 "This is a String"
瞧,现在我们已经给我们自己的对象添加了一个属性。可是,当我们新建一个myFunc对象的实例时(用构造方法myFunc()),我们也必须要手动的将同样的属性赋值给新的实例,例如:
function myFunc(){
}
var myObject = new myFunc();
myObject.StringValue = "This is a String";
var myObject2 = new myFunc();
alert(myObject2.StringValue); // 显示 "undefined"
那么,我们应该怎么操作才能给所有的myFunc对象实例添加属性呢?在操作方法内部,我们就可以做到。this这个关键字在构造方法内部的时候指向当前正被创建的对象实例。例如:
function myFunc(){
this.StringValue = "This is a String";
}
var myObject = new myFunc();
var myObject2 = new myFunc();
alert(myObject2.StringValue); // 显示 "This is a String"
现在,所有的myFunc对象都会有一个初始值为“this is a String”的字符串型的属性StringValue,同时每个对象实例的属性StringValue都可以拥有自己独特的值。也就是说,我们可以改变任何一个myFunc对象实例的stringValue属性的值,而不影响其他的myFunc实例:
function myFunc(){
this.StringValue = "This is a String";
}
var myObject = new myFunc();
myObject.StringValue = "This is myObject's string";
var myObject2 = new myFunc();
alert(myObject.StringValue); // 显示 "This is myObject's string"
alert(myObject2.StringValue); // 显示 "This is a String"
通过给构造方法添加参数的方法我们也可以达到相同的效果:
function myFunc(StringValue){
this.StringValue = StringValue;
}
var myObject = new myFunc("This is myObject's string");
var myObject2 = new myFunc("This is a String");
alert(myObject.StringValue); // 显示 "This is myObject's string"
alert(myObject2.StringValue); // 显示 "This is a String"
在myFunc()构造方法中,this.StringValue 指向当前创建的对象实例的StringValue属性,而StringValue则指向做为参数传过来的该方法的局部变量。这样,我们就把属性指向了对象实例,那方法有如何呢?(附:In the myFunc() constructor, this.StringValue refers to the property being assigned to the newly created object, while StringValue refers to the function's local variable that was passed as an argument. So, now that we've assigned properties to objects, what about methods?
原文里function和method翻译起来费劲,还是看一下原文吧要是没读懂。-、-)
对象方法
除了属性以外,对象也可以包含方法,对象的方法是一个可以执行的函数。来看看这个例子。下面这个例子中,我们创建一个Circle对象。首先我们要定义几个函数,然后将他们指定给我们的Circle对象。现在我们来定义Circle()构造函数,同时创建一到两个它的具体实例:,
function Circle(radius){
this.radius = radius;
}
var bigCircle = new Circle(100);
var smallCircle = new Circle(2);
然后,我们再定义两个可能用到的函数:
function getArea(){
return (this.radius*this.radius*3.14);
}
function getCircumference(){
var diameter = this.radius*2;
var circumference = diameter*3.14;
return circumference;
}
如果你要进行精确的计算的话,你可以用Math.PI来替代3.14,但这里我们就用pi的近似值来增强例子的可读性。
除了一个内容外这些函数都很简单:this.radius指向什么内容?this这个关键字总是指向当前对象,在这个例子里就是这个Circle对象。所以this.radius就指向了这个Circle对象的radius属性。那么,我们怎样将这两个函数添加到我们的对象中呢?事实上它没有你想象的那么麻烦。我们先来改改我们的Circle()构造器:
function Circle(radius){
this.radius = radius;
this.getArea = getArea;
this.getCircumference = getCircumference;
}
上面的代码将函数getArea和getCircumference添加到我们的Circle对象上,从而他们就成了我们的Circle对象中的方法。我们可以像使用其他函数一样使用对象的方法,但是我们必须通过一个包含它的具体的对象实例来调用它:
alert(bigCircle.getArea()); // 显示 31400
alert(bigCircle.getCircumference()); // 显示 618
alert(smallCircle.getArea()); // 显示 12.56
alert(smallCircle.getCircumference()); // 显示 12.56
保持整洁
如果我们想保持我们的属性和方法在相同的地方-Circle构造方法内部。有很多方法可以做到。先来看一下内部函数。内部函数就是在一个函数内部的函数。这是我们要做的:
function Circle(radius){
function getArea(){
return (this.radius*this.radius*3.14);
}
function getCircumference(){
var diameter = this.radius*2;
var circumference = diameter*3.14;
return circumference;
}
this.radius = radius;
this.getArea = getArea;
this.getCircumference = getCircumference;
}
除了方法的位置发生了变化其他都一样。现在在我们的两个函数内部,因为内部函数能取得包含它的外部函数的局部变量,我们用radius取代了this.radius。这样,它就能取得做为参数传递给外部函数Circle()构造器的局部变量了,这样我们就可以这样简单的使用了:
function Circle(radius){
function getArea(){
return (radius*radius*3.14);
}
function getCircumference(){
var diameter = radius*2;
var circumference = diameter*3.14;
return circumference;
}
this.radius = radius;
this.getArea = getArea;
this.getCircumference = getCircumference;
}
oK,现在让我们来改变一下一个对象的radius的值,然后去的它的面积:
bigCircle.radius=50;
alert(bigCircle.getArea()); // 显示 31400
瞧,先等等!返回值是31400,而不是期望的7850.哪里错了呢?好吧,radius引用了我们赋给构造方法的值,而不是对象的属性的值。这样我们虽然改变了对象的radius的值,但是方法getArea()和getCircumference(),还在使用旧的radius值。因此,我们应该使用指向了当前对象的this.radius,不管属性是在对象初始化的前后进行的改变。
OK,我们已经创建了一个完整的对象构造器(定义了一个对象的函数)。我们再来看看另一种在我们Circle()构造器内部建立方法的途径:
function Circle(radius){
this.radius = radius;
this.getArea = function(){
return (this.radius*this.radius*3.14);
}
this.getCircumference = function(){
var diameter = this.radius*2;
var circumference = diameter*3.14;
return circumference;
}
}
var bigCircle = new Circle(100);
var smallCircle = new Circle(2);
alert(bigCircle.getArea()); // displays 31400
alert(smallCircle.getCircumference()); // displays 12.56
在这里我们邂逅了另一种定义函数的法国是,我们可以这样做:
functionName = function([parameters]){
// function body
}
我们可以这样来建参数:
functionName = function(parameter1,parameter2,parameter3){
//function body
}
尽管这种建立函数的方法不是很常用,但是在建立对象时,这却是一个很好用的捷径。这个过程同样避免了同名方法的出现。例如,另一个对象可以拥有一个同名的不同方法,如:getArea() 而不会产生冲突。这种可能是因为这些函数被嵌套在了类构造器里。
对象种类
JavaScript总共有三种对象:原生对象,宿主对象,以及用户自定义对象。
原生对象是JavaScript自己内建的对象,如String,Number,Array,Image,Date,Math,等等。
宿主对象是浏览器支持的对象,如:window,document,forms等等
用户自定义对象就是程序员自己编写的对象了。
在JavaScript中,除了基本数据类型任何一个包含属性和方法的元素都是对象是它的基本思想。我们可以使用JavaScript的内建构造方法(就像我们已经创建的那样)去创建对象。
var Image1 = new Image(50,100);
Image1.src = "myDog.gif";
在这里我们使用了JavaScript自有的Image()构造函数创建了一个具有如下属性值的对象:
width = 50
height = 100
src = "myDog.gif"
JavaScript中也包含了一个基本的Object()构造器,也可以用它来创建一个对象:
var myObj = new Object();
我们可以给一个基本对象添加属性和方法,JavaScript中的所有对象都继承自JavaScript的基本的Object对象。
回顾一下一个基本数据类型的String:
var myString = "This is my string";
alert(myString); // 显示 "This is my string"
alert(typeof myString); // 显示 "string"
同时,我们也可以创建一个String类型的对象,通过这样的构造方法:
var myString = new String("This is my string");
alert(myString); // 显示 "This is my string"
alert(typeof myString); // 显示 "object"
现在我们构建了一个String类型的对象。我们也可以同样创建Number和Boolean类型的对象。但这样做又有什么好处呢?是的,一旦我们这样做了,就可以给这些对象添加独特的属性和方法。一个基本数据类型的实例包含了它的构造函数定义的属性和方法,但是它却不能拥有任何自己独有的属性和方法。例如,一个String基本类型就拥有length这个属性以及substring方法以及其它的通过它的构造函数获得的属性和方法。但是,一个String对象可以含有String()构造函数设置的属性和方法,也可以包含任何自己独有的特性。我们来创建一个Number对象,并给他添加一个方法:
var myNumber = new Number(2);
myNumber.doubleIt = new Function("return this*2");
alert(myNumber.doubleIt()); // 显示: 4
alert(typeof myNumber); // 显示"object"
我们仅仅创建了一个新的Number的对象实例,为它定义了一个方法:doubleIt()。请注意myNumber是一个“类对象”。这是因为对象可以包含自己独有的属性和方法,但是基本数据类型,如String,Boolean,Number,undefined,还有null却不能同样拥有。这是他们之间的区别。
可以看到,在上面的例子中,我们实际上创建了另外一个对象---一个Function对象。然而,这个Function对象是与众不同的。一般情况下,我们创建一个对象时,首先输入new关键字,然后紧跟着对象的构造函数,这样就可以返回一个普通的对象实例。接着我们就可以在生成的对象(通常用变量来保存)上添加属性和方法。可是,因为Function对象同时也是一整块可以调用的代码,JavaScript将它设置的与众不同,并且指出它不仅仅是一个对象(可以随意添加属性和方法),而且是一个可以调用的代码块。这样,当我们输入:
alert(typeof myNumber.doubleIt) // 显示 "function"
就像你希望的那样,显示了“function”而不是“object”。Function()构造函数可以接受一些参数(arguments)。除了最后一个参数成为了这个函数的函数体,其他的参数都成了你的函数的参数(parameters):
var myFunc = new Function("parameter1","parameter2",
"parameter3"," // function body");
现在我们可以传入三个参数来调用这个函数:
myFunc("argument1","argument2","argument3");
函数对象
因为很多原因JavaScript的Function对象变得不同寻常。首先,它包含一整块可调用的代码。再者,一个函数对象还是一个完整的对象—它总是有能力包含独特的属性和方法。建立函数时就自动的建立了一个Function对象:
function myFuncObj(){}
myFuncObj.someVariable = "x";
alert(myFuncObj.someVariable) // 显示 "x"
即使没有使用new关键字,Function()构造函数还是创建了一个对象,一个普通的能包含属性和方法的对象。请注意Function()构造器是一个特殊的构造器—其他的构造器都必须使用new关键字来调用,或者有一个简单数据类型的返回值而不是一个对象。
我们来看一下一个基本数据类型String,和一个String类的比较:
var pimitiveString1 = "This is a primitive string";
var pimitiveString2 = String("This is a primitive string");
var stringObject = new String("This is a String object");
primitiveString1.prop = "This is a property";
primitiveString2.prop = "This is a property";
stringObject.prop = "This is a property";
alert(primitiveString1.prop) // 显示 "undefined"
alert(primitiveString2.prop) // 显示 "undefined"
alert(stringObject.prop) // 显示 "This is a property"
alert(typeof primitiveString1); // 显示 "string"
alert(typeof primitiveString2); // 显示 "string"
alert(typeof stringObject) // 显示 "object"
你可以看到,不适用new关键字,我们无法创建一个对象并将它赋给一个变量,取而代之的是它将一个返回的基本数据类型(String基本类型)赋给了那个变量。你也可以看到primitiveString1 和 primitiveString2都不是对象,这样我们就不能给他们添加属性。当使用typeof关键字时primitiveString1/primitiveString2 和 stringObject 返回了不一样的结果。其他的如Date, Image, Option, 还有其他的类也一样。例如:
var x = Date();
alert(typeof x); // 显示 "string"
无论你怎么创建一个函数(很多方法)你会自动创建一个对象:
var myFuncObj = new Function();
var myFuncObj = Function();
var myFuncObj = function(){}
function myFuncObj()
这里我们用了不同的方法创建了Function对象,他们都能够包含一块可以调用的代码,同时也可以包含自己的属性和方法。 小结 继续之前,让我们来看几个关键点: JavaScript包含五种基本数据类型:Undefined, Null, Boolean, Number, 和 String. 在JavaScript中除了基本数据类型,一切都是对象。 对象是属性的无序集合。属性可以表现为基本数据类型,对象,函数对象(这里一般称为方法)。 总起来说JavaScript包含三种类别的对象,原生对象,宿主对象,以及用户自定义对象(就像我们前面定义的Circle对象)。 对象构造器/构造函数是一个用来创建一个新的对象类型的函数。在这个函数中我们定义了一个对象的基本属性和方法,通常也给他们赋了初始值。 可以使用new关键字调用构造器来创建一个对象的实例。我们既可以使用JavaScript内建的构造函数来创建一个原生对象,也可以使用自己定义的构造函数来创建一个自定义对象。 任何一个对象中都包含一个变量—this,它指向调用方法时候的那个实例对象,也就是当前对象,例如: myObj.myFunc() yourObj.myFunc() 第一个例子中,方法myFunc()中的this指向了myObj。而第二个例子中,myFunc()里的this是指向yourObj这个对象的。
原文地址:http://articles.sitepoint.com/article/oriented-programming-1/1
相关推荐
4. **类(Class)**:ES6引入了类语法糖,使得JavaScript的面向对象更加符合传统面向对象语言的写法,但实际上,这些“类”仍然基于原型实现。 ```javascript class Person { constructor(name) { this.name = ...
JavaScript是一种广泛应用于Web开发的轻量级脚本语言,它以基于对象的编程特性而闻名。基于对象编程意味着JavaScript不仅可以创建和操作对象,还可以利用现有对象的属性和方法进行编程。这种模型允许开发者以灵活的...
JavaScript是一种强大的基于对象的编程语言,它并非严格的面向对象编程(OOP)语言,而是以对象为基础。在JavaScript中,对象是由属性组成的集合,这些属性可以是基本数据类型、其他对象或是函数。JavaScript的五种...
### JavaScript基于对象编程的核心知识点 #### 一、对象的概念与特性 在JavaScript中,对象是基本的数据类型之一,它代表了现实世界中的实体,如猫、自行车或是文档中的`document`对象。对象拥有两个核心特性:...
1. 闭包(Closure)是一种JavaScript编程技术,用于实现基于类的面向对象编程。 2. 闭包可以用来模拟类的机制,并实现基于类的面向对象编程。 3. 基于闭包的JavaScript面向对象编程框架可以实现类的定义、继承和多态...
面向对象编程(Object-Oriented Programming,OOP)是一种编程范式,它基于“对象”的概念,允许程序员创建数据结构来表示和操作现实世界中的实体。在JavaScript中,OOP主要通过构造函数、原型链、闭包以及类(ES6...
面向对象编程(Object-Oriented Programming,OOP)是一种强大的编程范式,它基于“对象”的概念,允许我们通过封装数据和方法来组织代码。在JavaScript中,面向对象编程并不是原生支持的,但它可以通过模拟类和对象...
JavaScript的面向对象主要基于三个核心概念:封装、继承和多态。封装是将数据和操作这些数据的方法结合在一起,形成一个独立的单元,即对象。在JavaScript中,对象是键值对的集合,可以使用对象字面量或构造函数创建...
在JavaScript中,尽管它是一种原型基于的语言而不是传统的类(class)驱动的语言,但依然可以实现强大的面向对象功能。 #### JavaScript中的对象 在JavaScript中,一切皆对象。无论是内置类型如字符串、数字还是...
JavaScript是一种基于原型的语言,这意味着它不像传统的面向对象语言(如Java或C++)那样拥有类的概念。在JavaScript中,对象是核心,一切都可以视为对象。JavaScript的对象是动态的,即可以在运行时添加或删除属性...
2. **对象和原型**:JavaScript的面向对象特性基于原型,理解原型链、构造函数和实例化过程对于深入学习至关重要。 3. **闭包**:闭包是JavaScript中的一个重要概念,它允许函数访问并操作外部作用域的变量,同时...
JavaScript面向对象编程是一种基于原型(Prototype)的编程范式,它是动态类型语言,允许开发者创建具有复杂特性的对象。在JavaScript中,面向对象主要通过构造函数、原型链和闭包来实现。以下是对这一主题的详细...
《JavaScript编程精解 (第一版 带书签) 中文PDF扫描版》是一本专注于JavaScript(通常简称为JS)编程语言的书籍,涵盖了ES5(ECMAScript 2016标准)的编程技术。这本书适合那些希望提升前端开发技能的读者,特别是...
尽管有一些尝试构建面向对象或基于对象的操作系统,例如Spring、Choices和Clouds等,而且许多操作系统内部使用面向对象的概念(如vnodes),但在应用编程与操作系统开发之间仍然存在越来越大的差距。 ### 总结 1. ...
1. **基础语法**:JavaScript是一种基于原型的弱类型语言,它的基础包括变量声明(var、let、const)、数据类型(如字符串、数字、布尔、null、undefined、对象、数组、Symbol)、操作符(赋值、比较、逻辑、位操作...
**JavaScript编程基础** JavaScript是一种广泛应用于网页和网络应用的脚本语言,由网景公司的Brendan Eich在1995年创造。它主要负责客户端的交互,使得网页更加动态和用户友好。本课程“突破JavaScript编程实例五十...
1. **基于对象**:JavaScript中的所有数据都是对象,无论是基本类型如数字、字符串、布尔值,还是更复杂的自定义对象。这种基于对象的特性使得JavaScript具备了丰富的数据处理能力。 2. **封装**:通过函数和作用域...