[推荐]javascript 面向对象技术基础教程


Posted in Javascript onMarch 03, 2009

结果呢,看了大半天,有了一个大概的了解,细细一回味,好像什么都没懂...
这篇文章是参考<<javascript-the definitive guide,5th edition>>第7,8,9章而写成的,我也
会尽量按照原书的结构来说明javascript的面向对象技术(对象/数组->函数-->类/构造函数/原型).对一些我自己也拿捏不准的地方,我会附上原文的英文语句,供大家参考.
如果不做说明,则文中出现的所有英文语句(程序体除外)都是引自<<javascript-the definitive guide,5th edition>>.
-------------------------------------------------
对象和数组(Objects and Arrays)
什么是对象?把一些"名字-属性"的组合放在一个单元里面,就组成了一个对象.我们可以理解为javascript中
的对象就是一些"键-值"对的集合(An object is a collection of named values. These named values are usually referred
to as properties of the object.--Section3.5).
"名字"只能是string类型,不能是其他类型,而属性的类型则是
任意的(数字/字符串/其他对象..).可以用new Object()来创建一个空对象,也可以简单的用"{}"来创建一个
空对象,这两者的作用是等同的.

var emptyObject1 = {}; //创建空对象 
var emptyObject2 = new Object(); //创建空对象 
var person = {"name":"sdcyst", 
"age":18, 
"sex":"male"}; //创建一个包含初始值的对象person 
alert(person.name); //sdcyst 
alert(person["age"]); //18

从上面的例子我们也可以看到,访问一个对象的属性,可以简单的用对象名加"."后加属性的名字,也可以用"[]"操作符来获取,此时在[]里面的属性名字要加引号,这是因为对象中的索引都是字符串类型的. javasript对象中属性的个数是可变的,在创建了一个对象之后可以随时对它赋予任何的属性.
var person = {}; 
person.name = "sdcyst"; 
person["age"] = 18; 
alert(person.name + "__" + person.age); //sdcyst__18 
var _person = {name:"balala","age":23}; //在构建一个对象时,属性的名字可以不用引号来标注(name), 
//但是仍旧是一个字符串类型.在访问的时候[]内仍旧需要引号 
alert(_person["name"] + "__" + person.age); //balala__23 
alert(_person[name]); //undefinied 
var person = {}; 
person.name = "sdcyst"; 
person["age"] = 18; 
alert(person.name + "__" + person.age); //sdcyst__18 
var _person = {name:"balala","age":23}; //在构建一个对象时,属性的名字可以不用引号来标注(name), 
//但是仍旧是一个字符串类型.在访问的时候[]内仍旧需要引号 
alert(_person["name"] + "__" + person.age); //balala__23 
alert(_person[name]); //undefinied

通过"."操作符获取对象的属性,必须得知道属性的名字.一般来说"[]"操作符获取对象属性的功能更强大一些,

可以在[]中放入一些表达式来取属性的值,
比如可以用在循环控制语句中,而"."操作符则没有这种灵活性。

var name = {"name1":"NAME1","name2":"NAME2","name3":"NAME3","name4":"NAME4"}; 
var namestring = ""; 
for(var props in name) { //循环name对象中的属性名字 
namestring += name[props]; 
} 
alert(namestring); //NAME1NAME2NAME3NAME4 namestring = ""; 
for(var i=0; i<4; i++) { 
namestring += name["name"+(i+1)]; 
} 
alert(namestring); //NAME1NAME2NAME3NAME4

delete操作符可以删除对象中的某个属性,判断某个属性是否存在可以使用"in"操作符.
var name = {"name1":"NAME1","name2":"NAME2","name3":"NAME3","name4":"NAME4"}; 
var namestring = ""; 
for(var props in name) { //循环name对象中的属性名字 
namestring += name[props]; 
} 
alert(namestring); //NAME1NAME2NAME3NAME4 delete name.name1; //删除name1属性 
delete name["name3"]; //删除name3属性 
namestring = ""; 
for(var props in name) { //循环name对象中的属性名字 
namestring += name[props]; 
} 
alert(namestring); //NAME2NAME4 
alert("name1" in name); //false 
alert("name4" in name); //true

需要注意,对象中的属性是没有顺序的.

对象的constructor属性
每一个javascript对象都有一个constructor属性.这个属性对应了对象初始化时的构造函数(函数也是对象).

var date = new Date(); 
alert(date.constructor); //Date 
alert(date.constructor == "Date"); //false 
alert(date.constructor == Date); //true

数组
我们已经提到过,对象是无序数据的集合,而数组则是有序数据的集合,数组中的数据(元素)通过索引(从0开始)来访问,
数组中的数据可以是任何的数据类型.数组本身仍旧是对象,但是由于数组的很多特性,通常情况下把数组和对象区别
开来分别对待(Throughout this book, objects and arrays are often treated as distinct datatypes.
This is a useful and reasonable simplification; you can treat objects and arrays as separate types
for most of your JavaScript programming.To fully understand the behavior of objects and arrays,
however, you have to know the truth: an array is nothing more than an object with a thin layer of extra
functionality. You can see this with the typeof operator: applied to an array value, it returns
the string "object". --section7.5).
创建数组可以用"[]"操作符,或者是用Array()构造函数来new一个.

Js代码

var array1 = []; //创建空数组 
var array2 = new Array(); //创建空数组 
array1 = [1,"s",[3,4],{"name1":"NAME1"}]; // 
alert(array1[2][1]); //4 访问数组中的数组元素 
alert(array1[3].name1); //NAME1 访问数组中的对象 
alert(array1[8]); //undefined 
array2 = [,,]; //没有数值填入只有逗号,则对应索引处的元素为undefined 
alert(array2.length); //3 
alert(array2[1]); //undefined 
var array1 = []; //创建空数组 
var array2 = new Array(); //创建空数组 
array1 = [1,"s",[3,4],{"name1":"NAME1"}]; // 
alert(array1[2][1]); //4 访问数组中的数组元素 
alert(array1[3].name1); //NAME1 访问数组中的对象 
alert(array1[8]); //undefined 
array2 = [,,]; //没有数值填入只有逗号,则对应索引处的元素为undefined 
alert(array2.length); //3 
alert(array2[1]); //undefined

用new Array()来创建数组时,可以指定一个默认的大小,其中的值此时为undefined,以后可以再给他们赋值.但是由于

javascript中的数组的长度是可以任意改变的,同时数组中的内容也是可以任意改变的,因此这个初始化的长度实际上
对数组没有任何的约束力.对于一个数组,如果对超过它最大长度的索引赋值,则会改变数组的长度,同时会对没有赋值
的索引处赋值undefined,看下面的例子.

Js代码

var array = new Array(10); 
alert(array.length); //10 
alert(array[4]); //undefined 
array[100] = "100th"; //这个操作会改变数组的长度,同时将10-99索引对应的值设为undefined 
alert(array.length); //101 
alert(array[87]); //undefined 
var array = new Array(10); 
alert(array.length); //10 
alert(array[4]); //undefined 
array[100] = "100th"; //这个操作会改变数组的长度,同时将10-99索引对应的值设为undefined 
alert(array.length); //101 
alert(array[87]); //undefined

可以用delete操作符删除数组的元素,注意这个删除仅仅是将数组在该位置的元素设为undefined,数组的长度并没有改变.

我们已经使用过了数组的length属性,length属性是一个可以读/写的属性,也就是说我们可以通过改变数组的length属性来
任意的改变数组的长度.如果将length设为小于数组长度的值,则原数组中索引大于length-1的值都会被删除.如果length
的值大于原始数组的长度,则在它们之间的值设为undefined.

Js代码

var array = new Array("n1","n2","n3","n4","n5"); //五个元素的数组 
var astring = ""; 
for(var i=0; i<array.length; i++) { //循环数组元素 
astring += array[i]; 
} 
alert(astring); //n1n2n3n4n5 
delete array[3]; //删除数组元素的值 
alert(array.length + "_" + array[3]) //5_undefined array.length = 3; //缩减数组的长度 
alert(array[3]); //undefined 
array.length = 8; //扩充数组的长度 
alert(array[4]); //undefined 
var array = new Array("n1","n2","n3","n4","n5"); //五个元素的数组 
var astring = ""; 
for(var i=0; i<array.length; i++) { //循环数组元素 
astring += array[i]; 
} 
alert(astring); //n1n2n3n4n5 
delete array[3]; //删除数组元素的值 
alert(array.length + "_" + array[3]) //5_undefined 
array.length = 3; //缩减数组的长度 
alert(array[3]); //undefined 
array.length = 8; //扩充数组的长度 
alert(array[4]); //undefined

对于数组的其他方法诸如join/reverse等等,在这就不再一一举例.

通过上面的解释,我们已经知道,对象的属性值是通过属性的名字(字符串类型)来获取,而数组的元素是通过索
引(整数型 0~~2**32-1)来得到值.数组本身也是一个对象,所以对象属性的操作也完全适合于数组.

Js代码

var array = new Array("no1","no2"); 
array["po"] = "props1"; 
alert(array.length); //2 
//对于数组来说,array[0]同array["0"]效果是一样的(?不确定,测试时如此) 
alert(array[0] + "_" + array["1"] + "_" + array.po);//no1_no2_props1

函数
javascript函数相信大家都写过不少了,所以我们这里只是简单介绍一下.
创建函数:

function f(x) {........} 
var f = function(x) {......}

上面这两种形式都可以创建名为f()的函数,不过后一种形式可以创建匿名函数
函数定义时可以设置参数,如果传给函数的参数个数不够,则从最左边起依次对应,其余的用undefined赋值,如果传给函数
的参数多于函数定义参数的个数,则多出的参数被忽略.

Js代码

function myprint(s1,s2,s3) { 
alert(s1+"_"+s2+"_"+s3); 
} 
myprint(); //undefined_undefined_undefined 
myprint("string1","string2"); //string1_string2_undefined 
myprint("string1","string2","string3","string4"); //string1_string2_string3 
function myprint(s1,s2,s3) { 
alert(s1+"_"+s2+"_"+s3); 
} 
myprint(); //undefined_undefined_undefined 
myprint("string1","string2"); //string1_string2_undefined 
myprint("string1","string2","string3","string4"); //string1_string2_string3

因此,对于定义好的函数,我们不能指望调用者将所有的参数全部传进来.对于那些必须用到的参数应该在函数体中
加以检测(用!操作符),或者设置默认值然后同参数进行或(||)操作来取得参数.

Js代码

function myprint(s1,person) { 
var defaultperson = { //默认person对象 
"name":"name1", 
"age":18, 
"sex":"female" 
}; 
if(!s1) { //s1不允许为空 
alert("s1 must be input!"); 
return false; 
} 
person = person || defaultperson; //接受person对象参数 
alert(s1+"_"+person.name+":"+person.age+":"+person.sex); 
}; myprint(); //s1 must be input! 
myprint("s1"); //s1_name1:18:female 
myprint("s1",{"name":"sdcyst","age":23,"sex":"male"}); //s1_sdcyst:23:male 
function myprint(s1,person) { 
var defaultperson = { //默认person对象 
"name":"name1", 
"age":18, 
"sex":"female" 
}; 
if(!s1) { //s1不允许为空 
alert("s1 must be input!"); 
return false; 
} 
person = person || defaultperson; //接受person对象参数 
alert(s1+"_"+person.name+":"+person.age+":"+person.sex); 
}; 
myprint(); //s1 must be input! 
myprint("s1"); //s1_name1:18:female 
myprint("s1",{"name":"sdcyst","age":23,"sex":"male"}); //s1_sdcyst:23:male

函数的arguments属性
在每一个函数体的内部,都有一个arguments标识符,这个标识符代表了一个Arguments对象.Arguments对象非常类似
于Array(数组)对象,比如都有length属性,访问它的值用"[]"操作符利用索引来访问参数值,但是,二者是完全不同的
东西,仅仅是表面上有共同点而已(比如说修改Arguments对象的length属性并不会改变它的长度).

Js代码

function myargs() { 
alert(arguments.length); 
alert(arguments[0]); 
} 
myargs(); //0 --- undefined 
myargs("1",[1,2]); //2 --- 1 
function myargs() { 
alert(arguments.length); 
alert(arguments[0]); 
} 
myargs(); //0 --- undefined 
myargs("1",[1,2]); //2 --- 1 Arguments对象有一个callee属性,标示了当前Arguments对象所在的方法.可以使用它来实现匿名函数的内部递归调用.

Js代码
function(x) { 
if (x <= 1) return 1; 
return x * arguments.callee(x-1); 
} (section8.2) 
function(x) { 
if (x <= 1) return 1; 
return x * arguments.callee(x-1); 
} (section8.2)

Method--方法
方法就是函数.我们知道,每一个对象都包含0个或多个属性,属性可以是任意类型,当然也包括对象.函数本身就是一种
对象,因此我们完全可以把一个函数放到一个对象里面,此时,这个函数就成了对象的一个方法.此后如果要使用该方法,
则可以通过对象名利用"."操作符来实现.

Js代码

var obj = {f0:function(){alert("f0");}}; //对象包含一个方法 
function f1() {alert("f1");} 
obj.f1 = f1; //为对象添加方法 obj.f0(); //f0 f0是obj的方法 
obj.f1(); //f1 f1是obj的方法 
f1(); //f1 f1同时又是一个函数,可以直接调用 
f0(); //f0仅仅是obj的方法,只能通过对象来调用 
var obj = {f0:function(){alert("f0");}}; //对象包含一个方法 
function f1() {alert("f1");} 
obj.f1 = f1; //为对象添加方法 
obj.f0(); //f0 f0是obj的方法 
obj.f1(); //f1 f1是obj的方法 
f1(); //f1 f1同时又是一个函数,可以直接调用 
f0(); //f0仅仅是obj的方法,只能通过对象来调用

方法的调用需要对象的支持,那么在方法中如何获取对象的属性呢?this!this关键字我们已经很熟悉了,在javascript的方
法中,我们可以用this来取得对方法调用者(对象)的引用,从而获取方法调用者的各种属性.

Js代码

var obj = {"name":"NAME","sex":"female"}; 
obj.print = function() { //为对象添加方法 
alert(this.name + "_" + this["sex"]); 
}; 
obj.print(); //NAME_female 
obj.sex = "male"; 
obj.print(); //NAME_male 
var obj = {"name":"NAME","sex":"female"}; 
obj.print = function() { //为对象添加方法 
alert(this.name + "_" + this["sex"]); 
}; 
obj.print(); //NAME_female 
obj.sex = "male"; 
obj.print(); //NAME_male

下面我们来一个更加面向对象的例子.

Js代码

var person = {name:"defaultname", 
setName:function(s){ 
this.name = s; 
}, 
"printName":function(){ 
alert(this.name); 
}} 
person.printName(); //defaultname 
person.setName("newName"); 
person.printName(); //newName 
var person = {name:"defaultname", 
setName:function(s){ 
this.name = s; 
}, 
"printName":function(){ 
alert(this.name); 
}} 
person.printName(); //defaultname 
person.setName("newName"); 
person.printName(); //newName

在上面的例子中,完全可以用person.name=..来直接改变person的name属性,在此我们只是为了展示一下刚才提到的内容.
另一种改变person属性的方法就是:定义一个function,接收两个参数,一个是person,一个是name的值,看起来像是这样:
changeName(person,"newName").哪种方法好呢?很明显,例子中的方法更形象,更直观一些,而且好像有了那么一点面向
对象的影子.

再次强调一下,方法(Method)本身就是是函数(function),只不过方法的使用更受限制.在后面的篇幅中,如果提到函数,那么
提到的内容同样适用于方法,反之则不尽然.

函数的prototype属性
每一个函数都包含了一个prototype(原型)属性,这个属性构成了javascript面向对象的核心基础.在后面我们会详细讨论.

Javascript 相关文章推荐
一个网马的tips实现分析
Nov 28 Javascript
javascript 折半查找字符在数组中的位置(有序列表)
Dec 09 Javascript
document.addEventListener使用介绍
Mar 07 Javascript
使用js操作css实现js改变背景图片示例
Mar 10 Javascript
jQuery过滤选择器用法分析
Feb 10 Javascript
JavaScript模拟深蓝vs卡斯帕罗夫的国际象棋对局示例
Apr 22 Javascript
跟我学习javascript的undefined与null
Nov 17 Javascript
angular指令笔记ng-options的使用方法
Sep 18 Javascript
Servlet3.0与纯javascript通过Ajax交互的实例详解
Mar 18 Javascript
JavaScript常见JSON操作实例分析
Aug 08 Javascript
详解vue引入子组件方法
Feb 12 Javascript
解决ant Design Search无法输入内容的问题
Oct 29 Javascript
ajax 文件上传应用简单实现
Mar 03 #Javascript
escape、encodeURI 和 encodeURIComponent 的区别
Mar 02 #Javascript
javascript 文档的编码问题解决
Mar 01 #Javascript
jQuery Div中加载其他页面的实现代码
Feb 27 #Javascript
jQuery 使用个人心得
Feb 26 #Javascript
javascript div 弹出可拖动窗口
Feb 26 #Javascript
javascript URL锚点取值方法
Feb 25 #Javascript
You might like
php 服务器调试 Zend Debugger 的安装教程
2009/09/25 PHP
PHP+memcache实现消息队列案例分享
2014/05/21 PHP
PHP图片等比例缩放生成缩略图函数分享
2014/06/10 PHP
php取得字符串首字母的方法
2015/03/25 PHP
基于Laravel实现的用户动态模块开发
2017/09/21 PHP
PHP5.0~5.6 各版本兼容性cURL文件上传功能实例分析
2018/05/11 PHP
Phpstorm+Xdebug断点调试PHP的方法
2018/05/14 PHP
PHP中number_format()函数的用法讲解
2019/04/08 PHP
php7 图形用户界面GUI 开发示例
2020/02/22 PHP
PHP设计模式入门之迭代器模式原理与实现方法分析
2020/04/26 PHP
picChange 图片切换特效的函数代码
2010/05/06 Javascript
bootstrap输入框组代码分享
2016/06/07 Javascript
JavaScript实现公历转农历功能示例
2017/02/13 Javascript
vue中遇到的坑之变化检测问题(数组相关)
2017/10/13 Javascript
浅析从vue源码看观察者模式
2018/01/29 Javascript
详解webpack打包时排除其中一个css、js文件或单独打包一个css、js文件(两种方法)
2018/10/26 Javascript
Node.js在图片模板上生成二维码图片并附带底部文字说明实现详解
2019/08/07 Javascript
mpvue实现左侧导航与右侧内容的联动
2019/10/21 Javascript
vue cli4下环境变量和模式示例详解
2020/04/09 Javascript
[01:03:27]Optic vs VGJ.S 2018国际邀请赛小组赛BO2 第一场 8.17
2018/08/20 DOTA
在Python 字典中一键对应多个值的实例
2019/02/03 Python
Python实现去除列表中重复元素的方法总结【7种方法】
2019/02/16 Python
在python下使用tensorflow判断是否存在文件夹的实例
2019/06/10 Python
python实现PolynomialFeatures多项式的方法
2021/01/06 Python
中国网上药店领导者:1药网
2017/02/16 全球购物
美国羊皮公司:Overland
2018/01/15 全球购物
俄罗斯电子产品、计算机和家用电器购物网站:OLDI
2019/10/27 全球购物
幼儿师范毕业生自荐信
2013/11/09 职场文书
移风易俗倡议书
2014/04/15 职场文书
销售岗位职责范本
2014/06/12 职场文书
小学数学课题方案
2014/06/15 职场文书
2014保险公司内勤工作总结
2014/12/16 职场文书
导游词之山西-五老峰
2019/10/07 职场文书
《敬重卑微》读后感3篇
2019/11/26 职场文书
浅谈Python项目的服务器部署
2021/04/25 Python
Python还能这么玩之只用30行代码从excel提取个人值班表
2021/06/05 Python