javascript 声明类在使用字面量声明Object对象时,不会调用Object()构造函数 为什么

君,已阅读到文档的结尾了呢~~
扫扫二维码,随身浏览文档
手机或平板扫扫即可继续访问
JavaScript中对象字面量的理解
举报该文档为侵权文档。
举报该文档含有违规或不良信息。
反馈该文档无法正常浏览。
举报该文档为重复文档。
推荐理由:
将文档分享至:
分享完整地址
文档地址:
粘贴到BBS或博客
flash地址:
支持嵌入FLASH地址的网站使用
html代码:
&embed src='/DocinViewer--144.swf' width='100%' height='600' type=application/x-shockwave-flash ALLOWFULLSCREEN='true' ALLOWSCRIPTACCESS='always'&&/embed&
450px*300px480px*400px650px*490px
支持嵌入HTML代码的网站使用
您的内容已经提交成功
您所提交的内容需要审核后才能发布,请您等待!
3秒自动关闭窗口1.JavaScript基础
一个完整的JavaScript 应该由下列三个不同的部分组成。
1.核心(ECMAScript)
2.文档对象模型(DOM)
3.浏览器对象模型(BOM)
文档对象模型(DOM)
文档对象模型(DOM,Document Object Model)是针对XML 但经过扩展用于HTML 的应
用程序编程接口(API,Application Programming Interface)。
浏览器对象模型(BOM)
访问和操作浏览器窗口的浏览器对象模型(BOM,Browser Object Model)。开发人员使
用BOM 可以控制浏览器显示页面以外的部分。
2.JavaScript的使用
这组标签,是用于在html 页面中插入js 的主要方法。它主要有以下
几个属性:
1.charset:可选。表示通过src 属性指定的字符集。由于大多数浏览器忽略它,所以很
少有人用它。
2.defer:可选。表示脚本可以延迟到文档完全被解析和显示之后再执行。由于大多数浏
览器不支持,故很少用。
3.language:已废弃。原来用于代码使用的脚本语言。由于大多数浏览器忽略它,所以
不要用了。
4.src:可选。表示包含要执行代码的外部文件。
5.type:必需。可以看作是language 的替代品。表示代码使用的脚本语言的内容类型。
范例:type=”text/javascript”。
&script type="text/javascript"&
alert('欢迎来到JavaScript 世界!');
错误实例:
&script type="text/javascript" src="demo1.js" /&;
&script type="text/javascript" src="demo1.js"&alert('我很可怜,执行不到!')&/script&
平稳退化不支持JavaScript 处理:& nosciprt &
&noscript&
您没有启用JavaScript
&/noscript&
3.语法、关键保留字及变量
3.1语法构成
区分大小写
所谓标识符,就是指变量、函数、属性的名字,或者函数的参数。标识符可以是下列格
式规则组合起来的一或多个字符:
1.第一字符必须是一个字母、下划线(_)或一个美元符号($)。
2.其他字符可以是字母、下划线、美元符号或数字。
3.不能把关键字、保留字、true、false 和null 作为标识符。
例如:myName、book123 等
ECMAScript 使用C 风格的注释,包括单行注释和块级注释。
// 单行注释
* 这是一个多行
3.2关键字和保留字
ECMAScript 的变量是松散类型的,所谓松散类型就是用来保存任何类型的数据。定义
变量时要使用var 操作符(var 是关键),后面跟一个变量名(变量名是标识符)
alert(box);
定义后未初始化,系统会给它一个特殊的值– undefined(表示未定义)。
一条语句定义多个变量,只要把每个变量(初始化或者不初始化均可)用逗号分
4.数据类型
4.1typeof操作符
typeof 操作符是用来检测变量的数据类型。对于值或变量使用typeof 操作符会返回如下字符串。
对象或null
var box = '李炎恢';
alert(typeof box);
alert(typeof '李炎恢');
4.2数据类型
4.2.1Undefined类型
Undefined 类型只有一个值,即特殊的undefined。在使用var 声明变量,但没有对其初始化时,这个变量的值就是undefined。
alert(box);
PS:我们没有必要显式的给一个变量赋值为undefined,因为没有赋值的变量会隐式的(自动的)赋值为undefined;而undefined 主要的目的是为了用于比较,ECMAScript 第3 版之前并没有引入这个值,引入之后为了正式区分空对象与未经初始化的变量。
*未初始化的变量与根本不存在的变量(未声明的变量)也是不一样的。
alert(age); //age is not defined
PS:如果typeof box,typeof age 都返回的undefined。从逻辑上思考,他们的值,一个
是undefined,一个报错;他们的类型,却都是undefined。所以,我们在定义变量的时候,
尽可能的不要只声明,不赋值。
4.2.2Null类型
Null 类型是一个只有一个值的数据类型,即特殊的值null。它表示一个空对象引用(指
针),而typeof 操作符检测null 会返回object。
alert(typeof box);
有个要说明的是:undefined 是派生自null 的,因此ECMA-262 规定对它们的相等性测
试返回true。
alert(undefined == null);
由于undefined 和null 两个值的比较是相等的,所以,未初始化的变量和赋值为null 的
变量会相等。这时,可以采用typeof 变量的类型进行比较。
4.2.4Boolean类型
Boolean 类型有两个值(字面量):true 和false。而true 不一定等于1,false 不一定等于0。
JavaScript 是区分大小写的,True 和False 或者其他都不是Boolean 类型的值。
alert(typeof box);
虽然Boolean 类型的字面量只有true 和false 两种,但ECMAScript 中所有类型的值都有
与这两个Boolean 值等价的值。要将一个值转换为其对应的Boolean 值,可以使用转型函数
Boolean()。
var hello = ‘Hello World!’;
var hello2 = Boolean(hello);
alert(typeof hello);
上面是一种显示转换,属于强制性转换。而实际应用中,还有一种隐式转换。比如,在
if 条件语句里面的条件判断,就存在隐式转换。
var hello = ‘Hello World!’;
if (hello) {
alert(‘如果条件为true,就执行我这条!’);
alert(‘如果条件为false,就执行我这条!’);
4.2.5Number类型
Number 类型包含两种数值:整型和浮点型。
最基本的数值字面量是十进制整数。
var box = 100;
//十进制整数
八进制数值字面量,(以8 为基数),前导必须是0,八进制序列(0~7)。
var box = 070;
//八进制,56
var box = 079;
//无效的八进制,自动解析为79
var box = 08;
//无效的八进制,自动解析为8
十六进制字面量前面两位必须是0x,后面是(0~9 及A~F)。
var box = 0xA;
//十六进制,10
var box = 0x1f;
//十六进制,31
浮点类型,就是该数值中必须包含一个小数点,并且小数点后面必须至少有一位数字。
var box = 3.8;
var box = 0.8;
var box = .8;
//有效,但不推荐此写法
由于保存浮点数值需要的内存空间比整型数值大两倍,因此ECMAScript 会自动将可以
转换为整型的浮点数值转成为整型。
var box = 8.;
//小数点后面没有值,转换为8
var box = 12.0;
//小数点后面是0,转成为12
对于那些过大或过小的数值,可以用科学技术法来表示(e 表示法)。用e 表示该数值的
前面10 的指数次幂。
var box = 4.12e9;
var box = 0.;
//即4.12e-9
虽然浮点数值的最高精度是17 位小数,但算术运算中可能会不精确。由于这个因素,
做判断的时候一定要考虑到这个问题(比如使用整型判断)。
alert(0.1+0.2);
浮点数值的范围在:Number.MIN_VALUE ~ Number.MAX_VALUE 之间。
alert(Number.MIN_VALUE);
alert(Number.MAX_VALUE);
如果超过了浮点数值范围的最大值或最小值,那么就先出现Infinity(正无穷)或者
-Infinity(负无穷)。
var box = 100e1000;
//超出范围,Infinity
var box = -100e1000;
//超出范围,-Infinity
也可能通过Number.POSITIVE_INFINITY 和Number.NEGATIVE_INFINITY 得到Infinity(正无穷)及-Infinity(负无穷)的值。
alert(Number.POSITIVE_INFINITY);
//Infinity(正无穷)
alert(Number.NEGATIVE_INFINITY);
//-Infinity(负无穷)
要想确定一个数值到底是否超过了规定范围,可以使用isFinite()函数。如果没有超过,返回true,超过了返回false。
var box = 100e1000;
alert(isFinite(box)); //返回false 或者true
NaN,即非数值(Not a Number)是一个特殊的值,这个数值用于表示一个本来要返回数值的操作数未返回数值的情况(这样就不会抛出错误了)。比如,在其他语言中,任何数值除以0 都会导致错误而终止程序执行。但在ECMAScript 中,会返回出特殊的值,因此不会影响程序执行。
var box = 0 / 0; //NaN
var box = 12 / 0; //Infinity
var box = 12 / 0 * 0; //NaN
可以通过Number.NaN 得到NaN 值,任何与NaN 进行运算的结果均为NaN,NaN 与自
身不相等(NaN 不与任何值相等)。
alert(Number.NaN); //NaN
alert(NaN+1); //NaN
alert(NaN == NaN) //false
ECMAScript 提供了isNaN()函数,用来判断这个值到底是不是NaN。isNaN()函数在接收到一个值之后,会尝试将这个值转换为数值。
alert(isNaN(NaN)); //true
alert(isNaN(25)); //false,25 是一个数值
alert(isNaN(‘25’)); //false,’25’是一个字符串数值,可以转成数值
alert(isNaN(‘Lee’)); //true,’Lee’不能转换为数值
alert(isNaN(true)); //false true 可以转成成1
isNaN()函数也适用于对象。在调用isNaN()函数过程中,首先会调用valueOf()方法,然后确定返回值是否能够转换成数值。如果不能,则基于这个返回值再调用toString()方法,再测试返回值。
var box = {
toString : function () {
return ‘123’; //可以改成return ‘Lee’查看效果
alert(isNaN(box)); //false
有3 个函数可以把非数值转换为数值:Number()、parseInt()和parseFloat()。Number()函数是转型函数,可以用于任何数据类型,而另外两个则专门用于把字符串转成数值。
alert(Number(true)); //1,Boolean 类型的true 和false 分别转换成1 和0
alert(Number(25)); //25,数值型直接返回
alert(Number(null)); //0,空对象返回0
alert(Number(undefined)); //NaN,undefined 返回NaN
如果是字符串,应该遵循一下规则:
1.只包含数值的字符串,会直接转成成十进制数值,如果包含前导0,即自动去掉。
alert(Number(‘456’)); //456
alert(Number(‘070’)); //70
2.只包含浮点数值的字符串,会直接转成浮点数值,如果包含前导和后导0,即自动去掉。
alert(Number(‘08.90’)); //8.9
3.如果字符串是空,那么直接转成成0。
alert(Number(”)); //0
4.如果不是以上三种字符串类型,则返回NaN。
alert(‘Lee123’); //NaN
5.如果是对象,首先会调用valueOf()方法,然后确定返回值是否能够转换成数值。如果转换的结果是NaN,则基于这个返回值再调用toString()方法,再测试返回值。
var box = {
toString : function () {
return ‘123’; //可以改成return ‘Lee’查看效果
alert(Number(box)); //123
由于Number()函数在转换字符串时比较复杂且不够合理,因此在处理整数的时候更常用的是parseInt()。
alert(parsetInt(‘456Lee’)); //456,会返回整数部分
alert(parsetInt(‘Lee456Lee’)); //NaN,如果第一个不是数值,就返回NaN
alert(parseInt(‘12Lee56Lee’)); //12,从第一数值开始取,到最后一个连续数值结束
alert(parseInt(‘56.12’)); //56,小数点不是数值,会被去掉
alert(parseInt(”)); //NaN,空返回NaN
parseInt()除了能够识别十进制数值,也可以识别八进制和十六进制。
alert(parseInt(‘0xA’)); //10,十六进制
alert(parseInt(‘070’)); //56,八进制
alert(parseInt(‘0xALee’)); //100,十六进制,Lee 被自动过滤掉
ECMAScript 为parseInt()提供了第二个参数,用于解决各种进制的转换。
alert(parseInt(‘0xAF’)); //175,十六进制
alert(parseInt(‘AF’,16)); //175,第二参数指定十六进制,可以去掉0x 前导
alert(parseInt(‘AF’)); //NaN,理所当然
alert(parseInt(‘’,2)); //314,二进制转换
alert(parseInt(‘70’,8)) //56,八进制转换
parseFloat()是用于浮点数值转换的,和parseInt()一样,从第一位解析到非浮点数值位置。
alert(parseFloat(‘123Lee’)); //123,去掉不是别的部分
alert(parseFloat(‘0xA’)); //0,不认十六进制
alert(parseFloat(‘123.4.5’)); //123.4,只认一个小数点
alert(parseFloat(‘’)); //123.4,去掉前后导
alert(parseFloat(‘1.234e7’)); //,把科学技术法转成普通数值
4.2.6String类型
String 类型用于表示由于零或多个16 位Unicode 字符组成的字符序列,即字符串。字符串可以由双引号(“)或单引号(‘)表示。
var box = ‘Lee’;
var box = “Lee”;
PS:在某些其他语言(PHP)中,单引号和双引号表示的字符串解析方式不同,而ECMAScript 中,这两种表示方法没有任何区别。但要记住的是,必须成对出现,不能穿插使用,否则会出错。
var box = ‘李炎恢”; //出错
String 类型包含了一些特殊的字符字面量,也叫转义序列。
ECMAScript 中的字符串是不可变的,也就是说,字符串一旦创建,它们的值就不能改变。要改变某个变量保存的字符串,首先要销毁原来的字符串,然后再用另一个包含新值的字符串填充该变量。
var box = ‘Mr.’;
box = box + ’ Lee’;
toString()方法可以把值转换成字符串。
var box = 11;
alert(typeof box.toString());
toString()方法一般是不需要传参的,但在数值转成字符串的时候,可以传递进制参数。
var box = 10;
alert(box.toString()); //10,默认输出
alert(box.toString(2)); //1010,二进制输出
alert(box.toString(8)); //12,八进制输出
alert(box.toString(10)); //10,十进制输出
alert(box.toString(16)); //a,十六进制输出
如果在转型之前不知道变量是否是null 或者undefined 的情况下,我们还可以使用转型函数String(),这个函数能够将任何类型的值转换为字符串。
alert(String(box));
PS:如果值有toString()方法,则调用该方法并返回相应的结果;如果是null 或者undefined,则返回”null”或者”undeinfed”。
4.2.7Object类型
ECMAScript 中的对象其实就是一组数据和功能的集合。对象可以通过执行new 操作符后跟要创建的对象类型的名称来创建。
var box = new Object();
Object()是对象构造,如果对象初始化时不需要传递参数,可以不用写括号,但这种方式我们是不推荐的。
var box = new O
Object()里可以任意传参,可以传数值、字符串、布尔值等。而且,还可以进行相应的计算。
var box = new Object(2); //Object 类型,值是2
var age = box + 2; //可以和普通变量运算
alert(age); //输出结果,转型成Number 类型了
既然可以使用new Object()来表示一个对象,那么我们也可以使用这种new 操作符来创建其他类型的对象。
var box = new Number(5); //new String(‘Lee’)、new Boolean(true)
alert(typeof box); //Object 类型
一元运算符
只能操作一个值的运算符叫做一元运算符。
递增++和递减–
前置和后置
算术运算符
加减乘除求模(取余)
如果在算术运算的值不是数值,那么后台会先使用Number()转型函数将其转换为数值(隐式转换)。
关系运算符
用于进行比较的运算符称作为关系运算符:小于(&)、大于(&)、小于等于(&=)、大于等于(&=)、相等(==)、不等(!=)、全等(恒等)(===)、不全等(不恒等)(!==)
和其他运算符一样,当关系运算符操作非数值时要遵循一下规则:
1.两个操作数都是数值,则数值比较;
2.两个操作数都是字符串,则比较两个字符串对应的字符编码值;
3.两个操作数有一个是数值,则将另一个转换为数值,再进行数值比较;
4.两个操作数有一个是对象,则先调用valueOf()方法或toString()方法,再用结果比较;
var box = 3 & 2; //true
var box = 3 & 22; //false
var box = ‘3’ & 22; //false
var box = ‘3’ & ‘22’; //true
在相等和不等的比较上,如果操作数是非数值,则遵循一下规则:
1.一个操作数是布尔值,则比较之前将其转换为数值,false 转成0,true 转成1;
2.一个操作数是字符串,则比较之前将其转成为数值再比较;
3.一个操作数是对象,则先调用valueOf()或toString()方法后再和返回值比较;
4.不需要任何转换的情况下,null 和undefined 是相等的;
5.一个操作数是NaN,则==返回false,!=返回true;并且NaN 和自身不等;
6.两个操作数都是对象,则比较他们是否是同一个对象,如果都指向同一个对象,则返回true,否则返回false。
7.在全等和全不等的判断上,比如值和类型都相等,才返回true,否则返回false。
逻辑运算符
逻辑运算符通常用于布尔值的操作,一般和关系运算符配合使用,有三个逻辑运算符:
逻辑与(AND)、逻辑或(OR)、逻辑非(NOT)。
1.逻辑与(AND) :&&
如果两边的操作数有一个操作数不是布尔值的情况下,与运算就不一定返回布尔值,此时,遵循已下规则:
1.第一个操作数是对象,则返回第二个操作数;
2.第二个操作数是对象,则第一个操作数返回true,才返回第二个操作数,否则返回
3.有一个操作数是null,则返回null;
4.有一个操作数是undefined,则返回undefined。
2.逻辑或(OR):||
如果两边的操作数有一个操作数不是布尔值的情况下,逻辑与运算就不一定返回布尔
值,此时,遵循已下规则:
1.第一个操作数是对象,则返回第一个操作数;
2.第一个操作数的求值结果为false,则返回第二个操作数;
3.两个操作数都是对象,则返回第一个操作数;
4.两个操作数都是null,则返回null;
5.两个操作数都是NaN,则返回NaN;
6.两个操作数都是undefined,则返回undefined;
3.逻辑非(NOT):!
逻辑非运算符可以用于任何值。无论这个值是什么数据类型,这个运算符都会返回一个
布尔值。它的流程是:先将这个值转换成布尔值,然后取反,规则如下:
1.操作数是一个对象,返回false;
2.操作数是一个空字符串,返回true;
3.操作数是一个非空字符串,返回false;
4.操作数是数值0,返回true;
5.操作数是任意非0 数值(包括Infinity),false;
6.操作数是null,返回true;
7.操作数是NaN,返回true;
8.操作数是undefined,返回true;
一般的应用中,我们基本上用不到位运算符。
位运算符有七种,分别是:位非NOT(~)、位与AND(&)、位或OR(|)、位异或XOR(^)、
左移(&&)、有符号右移(&&)、无符号右移(&&&)。
赋值运算符
赋值运算符用等于号(=)表示,就是把右边的值赋给左边的变量。
除了这种+=加/赋运算符,还有其他的几种如下:
1.乘/赋(*=)
2.除/赋(/=)
3.模/赋(%=)
4.加/赋(+=)
5.减/赋(-=)
6.左移/赋(&&=)
7.有符号右移/赋(&&=)
8.无符号有移/赋(&&&=)
其他运算符
1.字符串运算符
字符串运算符只有一个,即:”+”。它的作用是将两个字符串相加。
2.逗号运算符
逗号运算符可以在一条语句中执行多个操作。
var box = (1,2,3,4,5); //5,变量声明,将最后一个值赋给变量,不常用
3.三元条件运算符
var box = 5 & 4 ? ‘对’ : ‘错’; //对,5&4 返回true 则把’对’赋值给box,反之。
运算符优先级
6.流程控制语句
for…in语句
for…in 语句是一种精准的迭代语句,可以用来枚举对象的属性。
var box = { //创建一个对象
‘name’ : ‘李炎恢’, //键值对,左边是属性名,右边是值
‘age’ : 28,
‘height’ : 178
for (var p in box) { //列举出对象的所有属性
with 语句的作用是将代码的作用域设置到一个特定的对象中。
var box = { //创建一个对象
‘name’ : ‘李炎恢’, //键值对
‘age’ : 28,
‘height’ : 178
var n = box. //从对象里取值赋给变量
var a = box.
var h = box.
可以将上面的三段赋值操作改写成:
with (box) { //省略了box 对象名
function box(name, age) { //带参数的函数
alert(‘你的姓名:’+name+’,年龄:’+age);
box(‘李炎恢’,28); //调用函数,并传参
return返回值
带参和不带参的函数,都没有定义返回值,而是调用后直接执行的。实际上,任何函数都可以通过return 语句跟后面的要返回的值来实现返回值。
function box() { //没有参数的函数
return ‘我被返回了!’; //通过return 把函数的最终值返回
alert(box()); //调用函数会得到返回值,然后外面输出
return 语句还有一个功能就是退出当前函数
arguments对象
ECMAScript 函数不介意传递进来多少参数,也不会因为参数不统一而错误。实际上,函数体内可以通过arguments 对象来接收传递进来的参数。
function box() {
return arguments[0]+’ | ‘+arguments[1]; //得到每次参数的值
alert(box(1,2,3,4,5,6)); //传递参数
arguments 对象的length 属性可以得到参数的数量。
function box() {
return arguments. //得到6
alert(box(1,2,3,4,5,6));
我们可以利用length 这个属性,来智能的判断有多少参数,然后把参数进行合理的应用。
比如,要实现一个加法运算,将所有传进来的数字累加,而数字的个数又不确定。
function box() {
var sum = 0;
if (arguments.length == 0)
//如果没有参数,退出
for(var i = 0;i & arguments. i++) {
//如果有,就累加
sum = sum + arguments[i];
//返回累加结果
alert(box(5,9,12));
8.对象和数组
什么是对象,其实就是一种类型,即引用类型。而对象的值就是引用类型的实例。
8.1Object 类型
创建Object 类型有两种。一种是使用new 运算符,一种是字面量表示法。
1.使用new 运算符创建Object
var box = new Object(); //new 方式
box.name = ‘李炎恢’; //创建属性字段
box.age = 28; //创建属性字段
2.new 关键字可以省略
var box = Object(); //省略了new 关键字
3.使用字面量方式创建Object
var box = { //字面量方式
name : ‘李炎恢’, //创建属性字段
4.属性字段也可以使用字符串星矢
var box = {
‘name’ : ‘李炎恢’, //也可以用字符串形式
‘age’ : 28
5.使用字面量及传统复制方式
var box = {}; //字面量方式声明空的对象
box.name = ‘李炎恢’; //点符号给属性复制
box.age = 28;
6.两种属性输出方式
alert(box.age); //点表示法输出
alert(box[‘age’]); //中括号表示法输出,注意引号
PS:在使用字面量声明Object 对象时,不会调用Object()构造函数(Firefox 除外)。
7.给对象创建方法
var box = {
run : function () { //对象中的方法
return ‘运行’;
alert(box.run()); //调用对象中的方法
8.使用delete 删除对象属性
delete box. //删除属性
在实际开发过程中,一般我们更加喜欢字面量的声明方式。因为它清晰,语法代码少,
而且还给人一种封装的感觉。字面量也是向函数传递大量可选参数的首选方式。
function box(obj) { //参数是一个对象
if (obj.name != undefined) alert(obj.name); //判断属性是否存在
if (obj.age != undefined) alert(obj.age);
box({ //调用函数传递一个对象
name : ‘李炎恢’,
8.2Array类型
创建Array 类型有两种方式:第一种是new 运算符,第二种是字面量。
1.使用new 关键字创建数组
var box = new Array(); //创建了一个数组
var box = new Array(10); //创建一个包含10 个元素的数组
var box = new Array(‘李炎恢’,28,’教师’,’盐城’); //创建一个数组并分配好了元素
2.以上三种方法,可以省略new 关键字。
var box = Array(); //省略了new 关键字
3 使用字面量方式创建数组
var box = []; //创建一个空的数组
var box = [‘李炎恢’,28,’教师’,’盐城’]; //创建包含元素的数组
var box = [1,2,]; //禁止这么做,IE 会识别3 个元素
var box = [,,,,,]; //同样,IE 的会有识别问题
PS:和Object 一样,字面量的写法不会调用Array()构造函数。(Firefox 除外)。
4.使用索引下标来读取数组的值
alert(box[2]); //获取第三个元素
box[2] = ‘学生’; //修改第三个元素
box[4] = ‘计算机编程’; //增加第五个元素
5.使用length 属性获取数组元素量
alert(box.length) //获取元素个数
box.length = 10; //强制元素个数
box[box.length] = ‘JS 技术’; //通过length 给数组增加一个元素
6.创建一个稍微复杂一点的数组
var box = [
{ //第一个元素是一个对象
name : ‘李炎恢’,
run : function () {
return ‘run 了’;
[‘马云’,’李彦宏’,new Object()],//第二个元素是数组
‘江苏’, //第三个元素是字符串
25+25, //第四个元素是数值
new Array(1,2,3) //第五个元素是数组
alert(box);
PS:数组最多可包含 个元素,超出即会发生异常。
8.3对象中的方法
对象或数组都具有toLocaleString()、toString()和valueOf()方法。其中toString()和valueOf()无论重写了谁,都会返回相同的值。数组会讲每个值进行字符串形式的拼接,以逗号隔开。
var box = [‘李炎恢’,28,’计算机编程’]; //字面量数组
alert(box); //隐式调用了toString()
alert(box.toString()); //和valueOf()返回一致
alert(box.toLocaleString()); //返回值和上面两种一致
默认情况下,数组字符串都会以逗号隔开。如果使用join()方法,则可以使用不同的分
隔符来构建这个字符串。
var box = [‘李炎恢’, 28, ‘计算机编程’];
alert(box.join(‘|’)); //李炎恢|28|计算机编程
ECMAScript 数组提供了一种让数组的行为类似于其他数据结构的方法。也就是说,可以让数组像栈一样,可以限制插入和删除项的数据结构。栈是一种数据结构(后进先出),也就是说最新添加的元素最早被移除。而栈中元素的插入(或叫推入)和移除(或叫弹出),只发生在一个位置——栈的顶部。ECMAScript 为数组专门提供了push()和pop()方法。
push()方法可以接收任意数量的参数,把它们逐个添加到数组的末尾,并返回修改后数组的长度。而pop()方法则从数组末尾移除最后一个元素,减少数组的length 值,然后返回移除的元素。
var box = [‘李炎恢’, 28, ‘计算机编程’]; //字面量声明
alert(box.push(‘盐城’)); //数组末尾添加一个元素,并且返回长度
alert(box); //查看数组
box.pop(); //移除数组末尾元素,并返回移除的元素
alert(box); //查看元素
栈方法是后进先出,而列队方法就是先进先出。列队在数组的末端添加元素,从数组的前端移除元素。通过push()向数组末端添加一个元素,然后通过shift()方法从数组前端移除一个元素。
var box = [‘李炎恢’, 28, ‘计算机编程’]; //字面量声明
alert(box.push(‘盐城’)); //数组末尾添加一个元素,并且返回长度
alert(box); //查看数组
alert(box.shift()); //移除数组开头元素,并返回移除的元素
alert(box); //查看数组
ECMAScript 还为数组提供了一个unshift()方法,它和shift()方法的功能完全相反。
unshift()方法为数组的前端添加一个元素。
var box = [‘李炎恢’, 28, ‘计算机编程’]; //字面量声明
alert(box.unshift(‘盐城’,’江苏’)); //数组开头添加两个元素
alert(box); //查看数组
alert(box.pop()); //移除数组末尾元素,并返回移除的元素
alert(box); //查看数组
PS:IE 浏览器对unshift()方法总是返回undefined 而不是数组的新长度。
重排序方法
数组中已经存在两个可以直接用来排序的方法:reverse()和sort()。
reverse() 逆向排序
var box = [1,2,3,4,5]; //数组
alert(box.reverse()); //逆向排序方法,返回排序后的数组
alert(box); //源数组也被逆向排序了,说明是引用
sort() 从小到大排序
var box = [4,1,7,3,9,2]; //数组
alert(box.sort()); //从小到大排序,返回排序后的数组
alert(box); //源数组也被从小到大排序了
sort 方法的默认排序在数字排序上有些问题,因为数字排序和数字字符串排序的算法是一样的。我们必须修改这一特征,修改的方式,就是给sort(参数)方法传递一个函数参数。这点可以参考手册说明。
function compare(value1, value2) { //数字排序的函数参数
if (value1 & value2) { //小于,返回负数
return -1;
} else if (value1 & value2) { //大于,返回正数
} else { //其他,返回0
var box = [0,1,5,10,15]; //验证数字字符串,和数字的区别
alert(box.sort(compare)); //传参
PS:如果要反向操作,即从大到小排序,正负颠倒即可。当然,如果要逆序用reverse()更加方便。
ECMAScript 为操作已经包含在数组中的元素提供了很多方法。concat()方法可以基于当前数组创建一个新数组。slice()方法可以基于当前数组获取指定区域元素并创建一个新数组。
splice()主要用途是向数组的中部插入元素。
var box = [‘李炎恢’, 28, ‘盐城’]; //当前数组
var box2 = box.concat(‘计算机编程’); //创建新数组,并添加新元素
alert(box2); //输出新数组
alert(box); //当前数组没有任何变化
var box = [‘李炎恢’, 28, ‘盐城’]; //当前数组
var box2 = box.slice(1); //box.slice(1,3),2-4 之间的元素
alert(box2); //28,盐城
alert(box); //当前数组
splice 中的删除功能:
var box = [‘李炎恢’, 28, ‘盐城’]; //当前数组
var box2 = box.splice(0,2); //截取前两个元素
alert(box2); //返回截取的元素
alert(box); //当前数组被截取的元素被删除
splice 中的插入功能:
var box = [‘李炎恢’, 28, ‘盐城’]; //当前数组
var box2 = box.splice(1,0,’计算机编程’,’江苏’); //没有截取,但插入了两条
alert(box2); //在第2 个位置插入两条
alert(box); //输出
splice 中的替换功能:
var box = [‘李炎恢’, 28, ‘盐城’]; //当前数组
var box2 = box.splice(1,1,100); //截取了第2 条,替换成100
alert(box2); //输出截取的28
alert(box); //输出数组
9.时间与日期
ECMAScript 中的Date 类型是在早期Java 中java.util.Date 类基础上构建的。为此,Date类型使用UTC (Coordinated Universal Time,国际协调时间[又称世界统一时间]) 1970 年1 月1 日午夜(零时)开始经过的毫秒来保存日期。在使用这种数据存储格式的条件下,Date 类型保存的日期能够精确到1970 年1 月1 日之前或之后的285616 年。
创建一个日期对象,使用new 运算符和Date 构造方法(构造函数)即可。
var box = new Date(); //创建一个日期对象
在调用Date 构造方法而不传递参数的情况下,新建的对象自动获取当前的时间和日期。
alert(box); //不同浏览器显示不同
ECMAScript 提供了两个方法,Date.parse()和Date.UTC()。Date.parse()方法接收一个表示日期的字符串参数,然后尝试根据这个字符串返回相应的毫秒数。ECMA-262 没有定义Date.parse()应该支持哪种日期格式,因此方法的行为因实现而异,因地区而异。默认通常接收的日期格式如下:
1.’月/日/年’,如6/13/2011;
2.’英文月名日, 年’,如May 25, 2004;
3.’英文星期几英文月名日年时:分:秒时区’,如Tue May 25 :00 GMT-070
alert(Date.parse(‘6/13/2011’)); //0
如果Date.parse()没有传入或者不是标准的日期格式,那么就会返NaN。
alert(Date.parse()); //NaN
如果想输出指定的日期,那么把Date.parse()传入Date 构造方法里。
var box = new Date(Date.parse(‘6/13/2011’));//Mon Jun 13 :00 GMT+0800
var box = new Date(‘6/13/2011’); //直接传入,Date.parse()后台被调用
Date.UTC()方法同样也返回表示日期的毫秒数,但它与Date.parse()在构建值时使用不同的信息。(年份,基于0 的月份[0 表示1 月,1 表示2 月],月中的哪一天[1-31],小时数[0-23],分钟,秒以及毫秒)。只有前两个参数是必须的。如果没有提供月数,则天数为1;如果省略其他参数,则统统为0.
alert(Date.UTC(2011,11)); //0
如果Date.UTC()参数传递错误,那么就会出现负值或者NaN 等非法信息。
alert(Date.UTC()); //负值或者NaN
如果要输出指定日期,那么直接把Date.UTC()传入Date 构造方法里即可。
var box = new Date(Date.UTC(, 15, 13, 16));
9.2通用的方法
与其他类型一样,Date 类型也重写了toLocaleString()、toString()和valueOf()方法;但这些方法返回值与其他类型中的方法不同。
var box = new Date(Date.UTC(, 15, 13, 16));
alert(‘toString:’ + box.toString());
alert(‘toLocaleString:’ + box.toLocaleString()); //按本地格式输出
PS:这两个方法在不同浏览器显示的效果又不一样,但不用担心,这两个方法只是在调试比较有用,在显示时间和日期上,没什么价值。valueOf()方法显示毫秒数。
9.3日期格式化方法
Date 类型还有一些专门用于将日期格式化为字符串的方法。
var box = new Date();
alert(box.toDateString()); //以特定的格式显示星期几、月、日和年
alert(box.toTimeString()); //以特定的格式显示时、分、秒和时区
alert(box.toLocaleDateString()); //以特定地区格式显示星期几、月、日和年
alert(box.toLocaleTimeString()); //以特定地区格式显示时、分、秒和时区
alert(box.toUTCString()); //以特定的格式显示完整的UTC 日期。
9.4组件方法
组件方法,是为我们单独获取你想要的各种时间/日期而提供的方法。需要注意的时候,这些方法中,有带UTC 的,有不带UTC 的。UTC 日期指的是在没有时区偏差的情况下的日期值。
alert(box.getTime()); //获取日期的毫秒数,和valueOf()返回一致
alert(box.setTime(100)); //以毫秒数设置日期,会改变整个日期
alert(box.getFullYear()); //获取四位年份
alert(box.setFullYear(2012)); //设置四位年份,返回的是毫秒数
alert(box.getMonth()); //获取月份,没指定月份,从0 开始算起
alert(box.setMonth(11)); //设置月份
alert(box.getDate()); //获取日期
alert(box.setDate(8)); //设置日期,返回毫秒数
alert(box.getDay()); //返回星期几,0 表示星期日,6 表示星期六
alert(box.setDay(2)); //设置星期几
alert(box.getHours()); //返回时
alert(box.setHours(12)); //设置时
alert(box.getMinutes()); //返回分钟
alert(box.setMinutes(22)); //设置分钟
alert(box.getSeconds()); //返回秒数
alert(box.setSeconds(44)); //设置秒数
alert(box.getMilliseconds()); //返回毫秒数
alert(box.setMilliseconds()); //设置毫秒数
alert(box.getTimezoneOffset()); //返回本地时间和UTC 时间相差的分钟数
PS:以上方法除了getTimezoneOffset(),其他都具有UTC 功能,例如setDate()及getDate()
获取星期几,那么就会有setUTCDate()及getUTCDate()。表示世界协调时间。
10正则表达式
10.1正则表达式的创建
1.两种创建方式
var box = new RegExp(‘box’); //第一个参数字符串
var box = new RegExp(‘box’, ‘ig’); //第二个参数可选模式修饰符
var box = /box/; //直接用两个反斜杠
var box = /box/ //在第二个斜杠后面加上模式修饰符
10.2测试正则表达式
RegExp 对象包含两个方法:test()和exec(),功能基本相似,用于测试字符串匹配。test()方法在字符串中查找是否存在指定的正则表达式并返回布尔值,如果存在则返回true,不存在则返回false。exec()方法也用于在字符串中查找指定正则表达式,如果exec()方法执行成功,则返回包含该查找字符串的相关信息数组。如果执行失败,则返回null。、
/使用new 运算符的test 方法示例/
var pattern = new RegExp(‘box’, ‘i’); //创建正则模式,不区分大小写
var str = ‘This is a Box!’; //创建要比对的字符串
alert(pattern.test(str)); //通过test()方法验证是否匹配
/使用字面量方式的test 方法示例/
var pattern = /box/i; //创建正则模式,不区分大小写
var str = ‘This is a Box!’;
alert(pattern.test(str));
/使用一条语句实现正则匹配/
alert(/box/i.test(‘This is a Box!’)); //模式和字符串替换掉了两个变量
/使用exec 返回匹配数组/
var pattern = /box/i;
var str = ‘This is a Box!’;
alert(pattern.exec(str)); //匹配了返回数组,否则返回null
10.3使用字符串的正则表达式方法
除了test()和exec()方法,String 对象也提供了4 个使用正则表达式的方法。
/使用match 方法获取获取匹配数组/
var pattern = /box/ //全局搜索
var str = ‘This is a Box!,That is a Box too’;
alert(str.match(pattern)); //匹配到两个Box,Box
alert(str.match(pattern).length); //获取数组的长度
/使用search 来查找匹配数据/
var pattern = /box/
var str = ‘This is a Box!,That is a Box too’;
alert(str.search(pattern)); //查找到返回位置,否则返回-1
PS:因为search 方法查找到即返回,也就是说无需g 全局
/使用replace 替换匹配到的数据/
var pattern = /box/
var str = ‘This is a Box!,That is a Box too’;
alert(str.replace(pattern, ‘Tom’)); //将Box 替换成了Tom
/使用split 拆分成字符串数组/
var pattern = / /
var str = ‘This is a Box!,That is a Box too’;
alert(str.split(pattern)); //将空格拆开分组成数组
/使用静态属性/
var pattern = /(g)oogle/;
var str = ‘This is google!’;
pattern.test(str); //执行一下
alert(RegExp.input); //This is google!
alert(RegExp.leftContext); //This is
alert(RegExp.rightContext); //!
alert(RegExp.lastMatch); //google
alert(RegExp.lastParen); //g
alert(RegExp.multiline); //false
RegExp.input 可以改写成RegExp [‘_’]&,依次类推。&&但RegExp.input&比较特殊,它还可以写成RegExp._。
/使用实例属性/
var pattern = /google/
alert(pattern.global); //true,是否全局了
alert(pattern.ignoreCase); //true,是否忽略大小写
alert(pattern.multiline); //false,是否支持换行
alert(pattern.lastIndex); //0,下次的匹配位置
alert(pattern.source); //google,正则表达式的源字符串
var pattern = /google/g;
var str = ‘google google google’;
pattern.test(str); //google,匹配第一次
alert(pattern.lastIndex); //6,第二次匹配的位
10.4获取控制
/关于贪婪和惰性/
var pattern = /[a-z]+?/; //?号关闭了贪婪匹配,只替换了第一个
var str = ‘abcdefjhijklmnopqrstuvwxyz’;
var result = str.replace(pattern, ‘xxx’);
alert(result);
var pattern = /8(.+?)8/g; //禁止了贪婪,开启的全局
var str = ‘This is 8google8, That is 8google8, There is 8google8’;
var result = str.replace(pattern,’& strong&1′);document.write(result);varpattern=/8([8]*)8/g;//另一种禁止贪婪varstr=‘Thisis8google8,Thatis8google8,Thereis8google8′;varresult=str.replace(pattern,′&strong&&script type=&math/tex& id=&MathJax-Element-2&&1’);
document.write(result);
var pattern = /8([^8]*)8/g; //另一种禁止贪婪
var str = ‘This is 8google8, That is 8google8, There is 8google8’;
var result = str.replace(pattern,’& strong&&/script&1’);
document.write(result);
/使用exec 返回数组/
var pattern = /^[a-z]+\s[0-9]{4}/i;varstr=‘google2012′;alert(pattern.exec(str));//返回整个字符串varpattern=/[a-z]+/i;//只匹配字母varstr=‘google2012′;alert(pattern.exec(str));//返回googlevarpattern=/([a-z]+)\s([0-9]4)&script type=&math/tex& id=&MathJax-Element-3&&/i;
var str = ‘google 2012’;
alert(pattern.exec(str)); //返回整个字符串
var pattern = /^[a-z]+/i; //只匹配字母
var str = ‘google 2012’;
alert(pattern.exec(str)); //返回google
var pattern = /^([a-z]+)\s([0-9]{4})&/script&/i; //使用分组
var str = ‘google 2012’;
alert(pattern.exec(str)[0]); //google 2012
alert(pattern.exec(str)[1]); //google
alert(pattern.exec(str)[2]); //2012
/捕获性分组和非捕获性分组/
var pattern = /(\d+)([a-z])/; //捕获性分组
var str = ‘123abc’;
alert(pattern.exec(str));
var pattern = /(\d+)(?:[a-z])/; //非捕获性分组
var str = ‘123abc’;
alert(pattern.exec(str));
/使用分组嵌套/
var pattern = /(A?(B?(C?)))/; //从外往内获取
var str = ‘ABC’;
alert(pattern.exec(str));
/使用前瞻捕获/
var pattern = /(goo(?=gle))/; //goo 后面必须跟着gle 才能捕获
var str = ‘google’;
alert(pattern.exec(str));
/使用特殊字符匹配/
var pattern = /.[\/b]/; //特殊字符,用\符号转义即可
var str = ‘.[/b]’;
alert(pattern.test(str));
/使用换行模式/
var pattern = /^\d+/ //启用了换行模式
var str = ‘1.baidu\n2.google\n3.bing’;
var result = str.replace(pattern, ‘#’);
alert(result);
10.5常用的正则
1.检查邮政编码
var pattern = /[1-9][0-9]{5}/; //共6 位数字,第一位不能为0
var str = ‘224000’;
alert(pattern.test(str));
2.检查文件压缩包
var pattern = /[\w]+.(zip|rar|gz)/; //\w 表示所有数字和字母加下划线
var str = ‘123.zip’; //.表示匹配.,后面是一个选择
alert(pattern.test(str));
3.删除多余空格
var pattern = /\s/g; //g 必须全局,才能全部匹配
var str = ‘111 222 333’;
var result = str.replace(pattern,”); //把空格匹配成无空格
alert(result);
4.删除首尾空格
var pattern = /^\s+/; //强制首
var str = ’ goo gle ‘;
var result = str.replace(pattern, ”);
pattern = /\s+$/; //强制尾
result = result.replace(pattern, ”);
alert(‘|’ + result + ‘|’);
var pattern = /^\s*(.+?)\s*$/; //使用了非贪婪捕获
var str = ’ google ‘;
alert(‘|’ + pattern.exec(str)[1] + ‘|’);
var pattern = /^\s*(.+?)\s*/;varstr=′google‘;alert(‘|′+str.replace(pattern,‘&script type=&math/tex& id=&MathJax-Element-4&&/;
var str = ’ google ‘;
alert(‘|’ + str.replace(pattern, ‘&/script&1’) + ‘|’); //使用了分组获取
5.简单的电子邮件验证
var pattern = /^([a-zA-Z0-9_.-]+)@([a-zA-Z0-9_.-]+).([a-zA-Z]{2,4})/;varstr=‘yc60.com@gmail.com′;alert(pattern.test(str));varpattern=/([\w.-]+)@([\w.-]+).([\w]2,4)/;
var str = ‘@’;
alert(pattern.test(str));
11.Function类型
11.1函数的声明方式
1.普通的函数声明
function box(num1, num2) {
return num1+ num2;
2.使用变量初始化函数
var box= function(num1, num2) {
return num1 + num2;
3.使用Function 构造函数
var box= new Function(‘num1’, ‘num2’ ,’return num1 + num2’);
ECMAScript 中的函数名本身就是变量,所以函数也可以作为值来使用。也就是说,不仅可以像传递参数一样把一个函数传递给另一个函数,而且可以将一个函数作为另一个函数的结果返回。
11.2函数内部属性
在函数内部,有两个特殊的对象:arguments 和this。arguments 是一个类数组对象,包含着传入函数中的所有参数,主要用途是保存函数参数。但这个对象还有一个名叫callee 的属性,该属性是一个指针,指向拥有这个arguments 对象的函数。
function box(num) {
if (num &= 1) {
return num * box(num-1); //一个简单的的递归
对于阶乘函数一般要用到递归算法,所以函数内部一定会调用自身;如果函数名不改变是没有问题的,但一旦改变函数名,内部的自身调用需要逐一修改。为了解决这个问题,我们可以使用arguments.callee 来代替。
function box(num) {
if (num &= 1) {
return num * arguments.callee(num-1);//使用callee 来执行自身
函数内部另一个特殊对象是this,其行为与Java 和C#中的this 大致相似。换句话说,this 引用的是函数据以执行操作的对象,或者说函数调用语句所处的那个作用域。PS:当在全局作用域中调用函数时,this 对象引用的就是window。
window.color = ‘红色的’; //全局的,或者var color = ‘红色的’;也行
alert(this.color); //打印全局的color
var box = {
color : ‘蓝色的’, //局部的color
sayColor : function () {
alert(this.color); //此时的this 只能box 里的color
box.sayColor(); //打印局部的color
alert(this.color); //还是全局的
11.3函数属性和方法
ECMAScript 中的函数是对象,因此函数也有属性和方法。每个函数都包含两个属性:length 和prototype。其中,length 属性表示函数希望接收的命名参数的个数。
function box(name, age) {
alert(name + age);
alert(box.length);
PS:对于prototype 属性,它是保存所有实例方法的真正所在,也就是原型。这个属性,我们将在面向对象一章详细介绍。而prototype 下有两个方法:apply()和call(),每个函数都包含这两个非继承而来的方法。这两个方法的用途都在特定的作用域中调用函数,实际上等于设置函数体内this 对象的值。
function box(num1, num2) {
return num1 + num2; //原函数
function sayBox(num1, num2) {
return box.apply(this, [num1, num2]); //this 表示作用域,这里是window
} //[]表示box 所需要的参数
function sayBox2(num1, num2) {
return box.apply(this, arguments); //arguments 对象表示box 所需要的参数
alert(sayBox(10,10)); //20
alert(sayBox2(10,10)); //20
call()方法于apply()方法相同,他们的区别仅仅在于接收参数的方式不同。对于call()方法而言,第一个参数是作用域,没有变化,变化只是其余的参数都是直接传递给函数的。
function box(num1, num2) {
return num1 + num2;
function callBox(num1, num2) {
return box.call(this, num1, num2); //和apply 区别在于后面的传参
alert(callBox(10,10));
事实上,传递参数并不是apply()和call()方法真正的用武之地;它们经常使用的地方是能够扩展函数赖以运行的作用域。
var color = ‘红色的’; //或者window.color = ‘红色的’;也行
var box = {
color : ‘蓝色的’
function sayColor() {
alert(this.color);
sayColor(); //作用域在window
sayColor.call(this); //作用域在window
sayColor.call(window); //作用域在window
sayColor.call(box); //作用域在box,对象冒充
这个例子是之前作用域理解的例子修改而成,我们可以发现当我们使用call(box)方法的时候,sayColor()方法的运行环境已经变成了box 对象里了。使用call()或者apply()来扩充作用域的最大好处,就是对象不需要与方法发生任何耦合关系(耦合,就是互相关联的意思,扩展和维护会发生连锁反应)。也就是说,box 对象和sayColor()方法之间不会有多余的关联操作,比如box.sayColor = sayC
12变量、作用域及内存
JavaScript 变量是松散型的(不强制类型)本质,决定了它只是在特定时间用于保存特定值的一个名字而已。由于不存在定义某个变量必须要保存何种数据类型值的规则,变量的值及其数据类型可以在脚本的生命周期内改
12.1变量及作用域
1.基本类型和引用类型的值
ECMAScript 变量可能包含两种不同的数据类型的值:基本类型值和引用类型值。基本类型值指的是那些保存在栈内存中的简单数据段,即这种值完全保存在内存中的一个位置。而引用类型值则是指那些保存在堆内存中的对象,意思是变量中保存的实际上只是一个指针,这个指针指向内存中的另一个位置,该位置保存对象。将一个值赋给变量时,解析器必须确定这个值是基本类型值,还是引用类型值。基本类型值有以下几种:Undefined、Null、Boolean、Number 和String。这些类型在内存中分别占有固定大小的空间,他们的值保存在栈空间,我们通过按值来访问的。
PS:在某些语言中,字符串以对象的形式来表示,因此被认为是引用类型。ECMAScript放弃这一传统。如果赋值的是引用类型的值,则必须在堆内存中为这个值分配空间。由于这种值的大小不固定,因此不能把它们保存到栈内存中。但内存地址大小的固定的,因此可以将内存地址保存在栈内存中。这样,当查询引用类型的变量时,先从栈中读取内存地址,然后再通过地址找到堆中的值。对于这种,我们把它叫做按引用访问。
2.动态属性
定义基本类型值和引用类型值的方式是相似的:创建一个变量并为该变量赋值。但是,
当这个值保存到变量中以后,对不同类型值可以执行的操作则大相径庭。
var box = new Object(); //创建引用类型
box.name = ‘Lee’; //新增一个属性
alert(box.name); //输出
如果是基本类型的值添加属性的话,就会出现问题了。
var box = ‘Lee’; //创建一个基本类型
box.age = 27; //给基本类型添加属性
alert(box.age); //undefined
3.复制变量值
在变量复制方面,基本类型和引用类型也有所不同。基本类型复制的是值本身,而引用
类型复制的是地址。
var box = ‘Lee’; //在栈内存生成一个box ‘Lee’
var box2 = //在栈内存再生成一个box2 ‘Lee’
box2 是虽然是box1 的一个副本,但从图示可以看出,它是完全独立的。也就是说,两
个变量分别操作时互不影响。
var box = new Object(); //创建一个引用类型
box.name = ‘Lee’; //新增一个属性
var box2 = //把引用地址赋值给box2
在引用类型中,box2 其实就是box,因为他们指向的是同一个对象。如果这个对象中的name 属性被修改了,box2.name 和box.name 输出的值都会被相应修改掉了。
4.传递参数
ECMAScript 中所有函数的参数都是按值传递的,言下之意就是说,参数不会按引用传递,虽然变量有基本类型和引用类型之分。
function box(num) { //按值传递,传递的参数是基本类型
num += 10; //这里的num 是局部变量,全局无效
var num = 50;
var result = box(num);
alert(result); //60
alert(num); //50
PS:以上的代码中,传递的参数是一个基本类型的值。而函数里的num 是一个局部变量,和外面的num 没有任何联系。下面给出一个参数作为引用类型的例子。
function box(obj) { //按值传递,传递的参数是引用类型
obj.name = ‘Lee’;
var p = new Object();
alert(p.name);
PS:如果存在按引用传递的话,那么函数里的那个变量将会是全局变量,在外部也可以访问。比如PHP 中,必须在参数前面加上&符号表示按引用传递。而ECMAScript 没有这些,只能是局部变量。可以在PHP 中了解一下。
PS:所以按引用传递和传递引用类型是两个不同的概念。
function box(obj) {
obj.name = ‘Lee’;
var obj = new Object(); //函数内部又创建了一个对象
obj.name = ‘Mr.’; //并没有替换掉原来的obj
最后得出结论,ECMAScript 函数的参数都将是局部变量,也就是说,没有按引用传递。
5.检测类型
要检测一个变量的类型,我们可以通过typeof 运算符来判别。诸如:
var box = ‘Lee’;
alert(typeof box); //string
虽然typeof 运算符在检查基本数据类型的时候非常好用,但检测引用类型的时候,它就不是那么好用了。通常,我们并不想知道它是不是对象,而是想知道它到底是什么类型的对象。因为数组也是object,null 也是Object 等等。这时我们应该采用instanceof 运算符来查看。
var box = [1,2,3];
alert(box instanceof Array); //是否是数组
var box2 = {};
alert(box2 instanceof Object); //是否是对象
var box3 = /g/;
alert(box3 instanceof RegExp); //是否是正则表达式
var box4 = new String(‘Lee’);
alert(box4 instanceof String); //是否是字符串对象
PS:当使用instanceof 检查基本类型的值时,它会返回false。
5.执行环境及作用域
执行环境是JavaScript 中最为重要的一个概念。执行环境定义了变量或函数有权访问的其他数据,决定了它们各自的行为。全局执行环境是最外围的执行环境。在Web 浏览器中,全局执行环境被认为是window对象。因此所有的全局变量和函数都是作为window 对象的属性和方法创建的。
var box = ‘blue’; //声明一个全局变量
function setBox() {
alert(box); //全局变量可以在函数里访问
setBox(); //执行函数
全局的变量和函数,都是window 对象的属性和方法。
var box = ‘blue’;
function setBox() {
alert(window.box); //全局变量即window 的属性
window.setBox(); //全局函数即window 的方法
PS:当执行环境中的所有代码执行完毕后,该环境被销毁,保存在其中的所有变量和函数定义也随之销毁。如果是全局环境下,需要程序执行完毕,或者网页被关闭才会销毁。
PS:每个执行环境都有一个与之关联的变量对象,就好比全局的window 可以调用变量和属性一样。局部的环境也有一个类似window 的变量对象,环境中定义的所有变量和函数都保存在这个对象中。(我们无法访问这个变量对象,但解析器会处理数据时后台使用它)函数里的局部作用域里的变量替换全局变量,但作用域仅限在函数体内这个局部环境。
var box = ‘blue’;
function setBox() {
var box = ‘red’; //这里是局部变量,出来就不认识了
alert(box);
alert(box);
通过传参,可以替换函数体内的局部变量,但作用域仅限在函数体内这个局部环境。
var box = ‘blue’;
function setBox(box) { //通过传参,替换了全局变量
alert(box);
setBox(‘red’);
alert(box);
函数体内还包含着函数,只有这个函数才可以访问内一层的函数。
var box = ‘blue’;
function setBox() {
function setColor() {
var b = ‘orange’;
alert(box);
setColor(); //setColor()的执行环境在setBox()内
PS:每个函数被调用时都会创建自己的执行环境。当执行到这个函数时,函数的环境
就会被推到环境栈中去执行,而执行后又在环境栈中弹出(退出),把控制权交给上一级的执
PS:当代码在一个环境中执行时,就会形成一种叫做作用域链的东西。它的用途是保
证对执行环境中有访问权限的变量和函数进行有序访问。作用域链的前端,就是执行环境的
变量对象。
6.没有块级作用域
块级作用域表示诸如if 语句等有花括号封闭的代码块,所以,支持条件判断来定义变
if (true) { //if 语句代码块没有局部作用域
var box = ‘Lee’;
alert(box);
for 循环语句也是如此
for (var i = 0; i & 10; i ++) { //没有局部作用域
var box = ‘Lee’;
alert(box);
var 关键字在函数里的区别
function box(num1, num2) {
var sum = num1 + num2; //如果去掉var 就是全局变量了
alert(box(10,10));
alert(sum); //报错
PS:非常不建议不使用var 就初始化变量,因为这种方法会导致各种意外发生。所以初
始化变量的时候一定要加上var。
一般确定变量都是通过搜索来确定该标识符实际代表什么。
var box = ‘blue’;
function getBox() {
//代表全局box
} //如果加上函数体内加上var box = ‘red’
alert(getBox()); //那么最后返回值就是red
12.2内存问题
JavaScript 具有自动垃圾收集机制,也就是说,执行环境会负责管理代码执行过程中使用的内存。其他语言比如C 和C++,必须手工跟踪内存使用情况,适时的释放,否则会造成很多问题。而JavaScript 则不需要这样,它会自行管理内存分配及无用内存的回收。JavaScript 最常用的垃圾收集方式是标记清除。垃圾收集器会在运行的时候给存储在内存中的变量加上标记。然后,它会去掉环境中正在使用变量的标记,而没有被去掉标记的变量将被视为准备删除的变量。最后,垃圾收集器完成内存清理工作,销毁那些带标记的值并回收他们所占用的内存空间。垃圾收集器是周期性运行的,这样会导致整个程序的性能问题。比如IE7 以前的版本,它的垃圾收集器是根据内存分配量运行的,比如256 个变量就开始运行垃圾收集器,这样,就不得不频繁地运行,从而降低的性能。一般来说,确保占用最少的内存可以让页面获得更好的性能。那么优化内存的最佳方案,就是一旦数据不再有用,那么将其设置为null 来释放引用,这个做法叫解除引用。这一做法适用于大多数全局变量和全局对象。
name : ‘Lee’
o = //解除对象引用,等待垃圾收集器回收
13基本包装类型
为了便于操作基本类型值,ECMAScript 提供了3 个特殊的引用类型:Boolean、Number
和String。这些类型与其他引用类型相似,但同时也具有与各自的基本类型相应的特殊行为。
实际上,每当读取一个基本类型值的时候,后台就会创建一个对应的基本包装类型的对象,
从而能够调用一些方法来操作这些数据。
13.1基本包装类型概述
var box = ‘Mr. Lee’; //定义一个字符串
var box2 = box.substring(2); //截掉字符串前两位
alert(box2); //输出新字符串
变量box 是一个字符串类型,而box.substring(2)又说明它是一个对象(PS:只有对象才
会调用方法),最后把处理结果赋值给box2。’Mr. Lee’是一个字符串类型的值,按道理它不
应该是对象,不应该会有自己的方法,比如:
alert(‘Mr. Lee’.substring(2)); //直接通过值来调用方法
1.字面量写法:
var box = ‘Mr. Lee’; //字面量
box.name = ‘Lee’; //无效属性
box.age = function () { //无效方法
return 100;
alert(box); //Mr. Lee
alert(box.substring(2)); //. Lee
alert(typeof box); //string
alert(box.name); //undefined
alert(box.age()); //错误
2.new 运算符写法:
var box = new String(‘Mr. Lee’); //new 运算符
box.name = ‘Lee’; //有效属性
box.age = function () { //有效方法
return 100;
alert(box); //Mr. Lee
alert(box.substring(2)); //. Lee
alert(typeof box); //object
alert(box.name); //Lee
alert(box.age()); //100
以上字面量声明和new 运算符声明很好的展示了他们之间的区别。但有一定还是可以
肯定的,那就是不管字面量形式还是new 运算符形式,都可以使用它的内置方法。并且
Boolean 和Number 特性与String 相同,三种类型可以成为基本包装类型。
PS:在使用new 运算符创建以上三种类型的对象时,可以给自己添加属性和方法,但
我们建议不要这样使用,因为这样会导致根本分不清到底是基本类型值还是引用类型值。
Boolean类型
Boolean 类型没有特定的属性或者方法。
Number类型
Number 类型有一些静态属性(直接通过Number 调用的属性,而无须new 运算符)和方
var box = ;
alert(box.toString()); //转换为字符串,传参可以转换进制
alert(box.toLocaleString()); //本地形式,1,000.789
alert(box.toFixed(2)); //小数点保留,1000.78
alert(box.toExponential()); //指数形式,传参会保留小数点
alert(box.toPrecision(3)); //指数或点形式,传参保留小数点
String类型
String 类型包含了三个属性和大量的可用内置方法。
String 也包含对象的通用方法,比如valueOf()、toLocaleString()和toString()方法,但这
些方法都返回字符串的基本值。
var box = ‘Mr.Lee’;
alert(box.charAt(1)); //r
alert(box.charCodeAt(1)); //114
alert(box[1]); //r,通过数组方式截取
PS:box[1]在IE 浏览器会显示undefined,所以使用时要慎重。
var box = ‘Mr.Lee’;
alert(box.concat(’ is ‘, ’ Teacher ‘, ‘!’)); //Mr.Lee is Teacher !
alert(box.slice(3)); //Lee
alert(box.slice(3,5)); //Le
alert(box.substring(3)); //Lee
alert(box.substring(3,5)); //Le
alert(box.substr(3)); //Lee
alert(box.substr(3,5)); //Lee
var box = ‘Mr.Lee’;
alert(box.slice(-3)); //Lee,6+(-3)=3 位开始
alert(box.substring(-3)); //Mr.Lee 负数返回全部
alert(box.substr(-3)); //Lee,6+(-3)=3 位开始
var box = ‘Mr.Lee’;
alert(box.slice(3, -1)); //Le 6+(-1)=5, (3,5)
alert(box.substring(3, -1)); //Mr. 第二参为负,直接转0,
//并且方法会把较小的数字提前,(0,3)
alert(box.substr(3, -1)); //” 第二参数为负,直接转0 ,(3,0)
PS:IE 的JavaScript 实现在处理向substr()方法传递负值的情况下存在问题,它会返回
原始字符串,使用时要切记。
var box = ‘Mr.Lee is Lee’;
alert(box.indexOf(‘L’)); //3
alert(box.indexOf(‘L’, 5)); //10
alert(box.lastIndexOf(‘L’)); //10
alert(box.lastIndexOf(‘L’, 5)); //3,从指定的位置向前搜索
PS:如果没有找到想要的字符串,则返回-1。
示例:找出全部的L
var box = ‘Mr.Lee is Lee’; //包含两个L 的字符串
var boxarr = []; //存放L 位置的数组
var pos = box.indexOf(‘L’); //先获取第一个L 的位置
while (pos & -1) { //如果位置大于-1,说明还存在L
boxarr.push(pos); //添加到数组
pos = box.indexOf(‘L’, pos + 1); //从新赋值pos 目前的位置
alert(boxarr); //输出
var box = ‘Mr.Lee is Lee’;
alert(box.toLowerCase()); //全部小写
alert(box.toUpperCase()); //全部大写
alert(box.toLocaleLowerCase()); //
alert(box.toLocaleUpperCase()); //
PS:只有几种语言(如土耳其语)具有地方特有的大小写本地性,一般来说,是否本
地化效果都是一致的。
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:312次
排名:千里之外

我要回帖

更多关于 javascript 声明数组 的文章

 

随机推荐