JavaScript笔记(二)
二、基于对象的JavaScript
1. JS对象概述
1.1. 基本类型与对象
原始类型和引用类型
在ECMAScript(JavaScript)中,变量有两种类型,即原始类型和引用类型。
- 原始类型:原始类型的值存储在栈(stack)中。
- 引用类型:引用类型存储的是一个指针。指向存储在堆中的对象。
JavaScript有五种原始类型:Undefined、Null、Boolean、Number和String。
typeof 运算符
- typeof 运算符有一个参数,即要检查的变量或值
(java中判断变量属于哪种类型:instanceof) - 如果变量是一种引用类型或Null类型的:“object”
(html中的所元素都是对象) - 判断变量类型,如果判断对象返回的都是object
- 在使用 typeof 运算符时采用引用类型存储值会出现一个问题,无论引用的是什么类型的对象,它都返回 “object”。到底是个什么对象??——引入instanceof
instanceof 运算符
instanceof 方法要求开发者明确地确认对象的特定类型(对基本数据类型不起作用,全返回false)。
- js数据类型分为两种
基本数据类型:Undefined、Null、Boolean、Number和String
对象类型(instanceof 只对对象判断,对基本数据类型无效都返回false) - js中所有new出来的全是对象
- 所有“对象”都是object的子类
var oStringObject = new String("hello world");
alert(oStringObject instanceof String); //输出 "true"
// 所有“对象”都是object的子类
var str2 = "sssss";
var str19 = new String("sssss");
document.write("typeof str2 :" + typeof str2 + "<br/>"); //string
// 对基本数据类型使用 instanceof 返回的全是false,instanceof只对对象有用。
document.write("str2 instanceof String :" + (str2 instanceof String) + "<br/>"); // false
document.write("str2 instanceof Object :" + (str2 instanceof Object) + "<br/>"); // false
document.write("typeof str19 :" + typeof str19 + "<br/>"); // object。js中所有new出来的全是对象
document.write("str19 instanceof String :" + (str19 instanceof String) + "<br/>"); // true
document.write("str19 instanceof Object :" + (str19 instanceof Object) + "<br/>"); // true
1.2. JS对象类型
本地对象(内置的类)
Object、Function、Array、String、Boolean、Number、Date、RegExp、Error、EvalError、RangeError、ReferenceError、SyntaxError、TypeError、URIError
由此可以看出,简单来说,本地对象就是 ECMA-262 定义的类(引用类型)。(相当于JavaScript提供的类)
var arr = new Array();
内置对象
ECMA-262 把内置对象(built-in object)定义为“由 ECMAScript 实现提供的、独立于宿主环境的所有对象,在 ECMAScript 程序开始执行时出现”。这意味着开发者不必明确实例化内置对象,它已被实例化了。
只定义了两个内置对象,即 Global 和 Math
Math. (会提示很多,不用new)
宿主对象
由ECMAScript实现的宿主环境提供的对象,可以理解为:浏览器提供的对象。所有的BOM和DOM都是宿主对象。
如Window和Document等。
自定义对象
开发人员自己定义的对象。JS允许使用自定义对象,使JS应用及功能得到扩充。(见三)
2. 对象(Object)
顶级父类,所有对象都继承object
3. 全局对象(Global)
实际上它根本不存在。如果尝试编写下面的代码,将会出错。
var v = Global;
错误消息显示Global不是对象。
用的所有系统提供的函数,实际都是Global。例如:alert() —— Global.alert()
encodeURI()、encodeURIComponent()、decodeURI()、decodeURIComponent()
encodeURI() 和 encodeURIComponent() 方法用于编码传递给浏览器的URI(统一资源定位符)。有效的URI不能包含某些字符,比如空格。
这两个方法用于编码URI,这样用专门的UTF-8编码替换所有的非有效的字符,就可以使浏览器理解他们。
encodeURI()方法用于处理完整的URI(例如:http://www.baidu.com/home index.html)
encodeURIComponent()用于处理URI的一个片段(如前面的URI的home index.html)
- 主要区别:
encodeURI()方法不对URI中的特殊字符进行编码,如冒号、前斜杠、问好、英镑符号
encodeURIComponent()则对它发现的所有非标准字符进行编码。
var sUri = “http://www.wrox.com/illegal value.htm#start”;
document.write("encodeURI(sUri):" + encodeURI(sUri) + '<br/>');
document.write("encodeURIComponent(sUri):" + encodeURIComponent(sUri));
var sUri1 = "http://www.wrox.com/";
var sUri1Component = "illegal value.htm#start";
document.write(sUri1 + encodeURIComponent(sUri1Component));
输出的结果:
- 解码:
decodeURI()针对的是encodeURI() ,
decodeURIComponent()是针对encodeURIComponent()。
eval()
eval()里面是js脚本,可以直接执行。
该函数就像是整个ECMAScript的解释程序一样。接受一个参数,即要执行的ECMAScript字符串。
// eval
eval("alert('hi')");
var msg = "hello world";
eval('alert(msg)');
eval("function sayHi(){alert('hi');}");
sayHi();
homework:做一个计算器
4. 布尔(Boolean)
要创建Boolean对象,只需要传递Boolean值作为参数:
var objBoolean = new Boolean(true);
在这行代码中,计算的是oFalseObject,而不是它的值false。
在Boolean表达式中,所有的对象都会被自动转换为true,oFalseObject是个对象,所以它的值是true。
所以最终结果是true。与事实不符。所以应该避免使用 Boolean对象。
var oFalseObject = new Boolean(false);
alert(oFalseObject); // false
var bResult = oFalseObject && true;
alert(bResult); // true
- Boolean() 强制转换规则
// 有意义的转换为true,无意义的转换成false
var b1 = Boolean(""); //false 空字符串
var b2 = Boolean(“hi”); //true 非空字符串
var b3 = Boolean(100); //true 非0数字
var b4 = Boolean(null); //false null
var b5 = Boolean(0); //false 0
var b6 = Boolean(new Object()); //true object
5. 数字
5.1. JavaScript数字
-
整数值得变量,它的值由字面量255定义:
var num1 = 255; -
八进制
var num1=070;
alert(num1); // 56 -
十六进制
var num2 = 0x1f;
alert(num2); // 31
Var num3 = 0xAB; -
要定义浮点数
var num4 = 6.0; -
注意:尽管所有的整数都可以表示为八进制和十六进制的字面量,但是所有的数学运算返回的都是十进制结果。
5.2. Number对象
Number 对象是原始数值的包装对象。
- 创建 Number 对象的语法:
var myNum=new Number(value);
var myNum=Number(value);
5.3. 类型转换
1. Number() 的强制类型转换(了解)
Number()的转换规则如下。
Number(false) //结果0
Number(true) //结果1
Number(undefined) //结果NaN
Number(null) //0
Number(“5.5”) //5.5
Number(“56”) //56
Number(“5.6.7”) //NaN
Number(new Object()) //NaN
Number(100) //100
2. Global对象的parseInt()和parseFloat()
parseInt()和parseFloat()是JavaScript 提供的两种把非数字的原始值转换为数字的方法。
前者把值转为整数,后者把值转为浮点数。
只有对String类型调用这些方法,它们才能正常运行。对其他类型返回的都是NaN。
- parseInt()
var num1 = parseInt("1234aaaaa"); //结果 1234
var num2 = parseInt("0xA"); //0x开头 16进制结果 10
var num3 = parseInt("070"); //0开头 8进制结果??? 70(坑)
var num4 = parseInt("1234.8"); //结果 1234
var num5 = parseInt("aaaaa"); //结果 NaN
- parseFloat()
var fNum1 = parseFloat("12345red"); //返回 12345
var fNum2 = parseFloat("0xA"); //返回 NaN
var fNum3 = parseFloat("11.2"); //返回 11.2
var fNum4 = parseFloat("11.22.33"); //返回 11.22
var fNum5 = parseFloat("0102"); //返回 102
var fNum1 = parseFloat("red"); //返回 NaN
3. 进制转换
-
parseInt() 方法的基模式
可以把二进制、八进制、十六进制或其他任何进制的字符串转换成10制整数。document.write("parseInt('96',16):" + parseInt('96',16) + "<br/>"); document.write("parseInt('226',8):" + parseInt('226',8) + "<br/>"); document.write("parseInt('10010110',2):" + parseInt('10010110',2) + "<br/>");
-
将10进制整数转换为2进制、8进制、16进制
var num_10 = 150; document.write("num_10.toString():" + num_10.toString() + "<br/>"); document.write("num_10.toString(2):" + num_10.toString(2) + "<br/>"); document.write("num_10.toString(8):" + num_10.toString(8) + "<br/>"); document.write("num_10.toString(16):" + num_10.toString(16) + "<br/>"); var num_11 = 150.15; document.write("num_10.toString():" + num_11.toString() + "<br/>"); document.write("num_10.toString(2):" + num_11.toString(2) + "<br/>"); document.write("num_10.toString(8):" + num_11.toString(8) + "<br/>"); document.write("num_10.toString(16):" + num_11.toString(16) + "<br/>");
4. 特殊的Number值
- Number.MAX_VALUE、Number.MIN_VALUE,Number.POSITIVE_INFINITY、Number.NEGATIVE_INFINITY
document.write("Number.MAX_VALU:" + Number.MAX_VALUE + "<br/>"); // 最大值
document.write("Number.MIN_VALUE:" + Number.MIN_VALUE + "<br/>"); // 最小值
// 当计算生成的数大于 Number.MAX_VALUE 或小于 Number.MIN_VALUE 时,
// 它将被赋予值 Number.POSITIVE_INFINITY 或 Number.NEGATIVE_INFINITY
document.write("Number.POSITIVE_INFINITY:" + Number.POSITIVE_INFINITY + "<br/>"); // 正无穷大
document.write("Number.NEGATIVE_INFINITY:" + Number.NEGATIVE_INFINITY + "<br/>"); // 负无穷大
- isFinite()
// isFinite()
// 由于无穷大数可以是正数也可以是负数,所以可用一个方法判断一个数是否是有穷的。
// 万一超出范围,程序可能出现问题,做一个提醒(类似异常处理)
// 可以对任何数调用 isFinite() 方法,以确保该数不是无穷大。
// isFinite(num) 判断num是否在Number的有效范围内
var iResult = iNum * some_really_large_number;
if(isFinite(iResult)) {
alert("finite");
} else {
alert("infinite");
}
- isNaN()
// isNaN() 是否是非数字(Not a Number):不是数字true,数字false
// NaN 的另一个奇特之处在于,它与自身不相等
alert(NaN == NaN); //输出 "false"
alert(isNaN("blue")); //输出 "true"
alert(isNaN("666")); //输出 "false"
document.write("isNaN(''):" + isNaN('') + "<br/>"); // false
document.write("isNaN(null):" + isNaN(null) + "<br/>"); // false
document.write("isNaN(undefined):" + isNaN(undefined) + "<br/>"); // true
6. 字符串(String)
String 对象用于处理文本(字符串)。
- 创建 String 对象的语法:
new String(s);
String(s);
var str = "abc, 23, sad";
var arr = str.split(",");
for(var i in arr){
document.write(arr[i] + "<br>");
}
7. 日期(Date)
Date 对象用于处理日期和时间。
- 创建 Date 对象的语法:
var myDate=new Date([arguments list]);
注释:Date 对象会自动把当前日期和时间保存为其初始值。
- 获取当前日期:
new Date(); // 格式不是很友好,可以自定义格式 - 获取指定日期:
1)new Date(“month dd,yyyy hh:mm:ss”);
2)new Date(“month dd,yyyy”);
3)new Date(yyyy,mth,dd,hh,mm,ss); alert(new Date(2017,0,12,22,19,35));
4)new Date(yyyy,mth,dd);
5)new Date(ms); - 日期格式化
(new Date()).format("yyyy-MM-dd hh:mm:ss.S") == > 2006 - 07 - 02 08: 09: 04.423 *
(new Date()).format("yyyy-MM-dd E HH:mm:ss") == > 2009 - 03 - 10 二 20: 09: 04 *
(new Date()).format("yyyy-MM-dd EE hh:mm:ss") == > 2009 - 03 - 10 周二 08: 09: 04 *
(new Date()).format("yyyy-MM-dd EEE hh:mm:ss") == > 2009 - 03 - 10 星期二 08: 09: 04
(new Date()).format("yyyy-M-d h:m:s.S") == > 2006 - 7 - 2 8: 9: 4.18 */
// 日期格式化:直接加上这个代码就可以,放在使用new Date() 之前
Date.prototype.format = function(fmt) {
var o = {
"M+": this.getMonth() + 1, //月份
"d+": this.getDate(), //日
"h+": this.getHours() % 12 == 0 ? 12 : this.getHours() % 12, //小时
"H+": this.getHours(), //小时
"m+": this.getMinutes(), //分
"s+": this.getSeconds(), //秒
"q+": Math.floor((this.getMonth() + 3) / 3), //季度
"S": this.getMilliseconds() //毫秒
};
var week = {
"0": "/u65e5",
"1": "/u4e00",
"2": "/u4e8c",
"3": "/u4e09",
"4": "/u56db",
"5": "/u4e94",
"6": "/u516d"
};
if(/(y+)/.test(fmt)) {
fmt = fmt.replace(RegExp.$1, (this.getFullYear() + "").substr(4 - RegExp.$1.length));
}
if(/(E+)/.test(fmt)) {
fmt = fmt.replace(RegExp.$1, ((RegExp.$1.length > 1) ? (RegExp.$1.length > 2 ? "/u661f/u671f" : "/u5468") : "") + week[this.getDay() + ""]);
}
for(var k in o) {
if(new RegExp("(" + k + ")").test(fmt)) {
fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k]).length)));
}
}
return fmt;
}
alert(new Date().format("yyyy-MM-dd hh:mm:ss.S")); // 日期格式化
8. 数组(Array)
- 创建名为 cars 的数组:
var cars=new Array();
//也可以指定长度,比如 new Array(10);
//当调用构造函数时只传递给它一个数字参数,该构造函数将返回具有指定个数、元素为 undefined 的数组。
cars[0]="Audi";
cars[1]="BMW";
cars[2]="Volvo";
// 或者 (condensed array):
var cars=new Array("Audi","BMW","Volvo");
// 或者 (literal array):
var cars=["Audi","BMW","Volvo"];
- 方法
9. 算数(Math,不需要new)
- 使用 Math 的属性和方法的语法:
var pi_value=Math.PI;
var sqrt_value=Math.sqrt(15);
- 注释:Math 对象并不像 Date 和 String 那样是对象的类,因此没有构造函数 Math(),像 Math.sin() 这样的函数只是函数,不是某个对象的方法。您无需创建它,通过把 Math 作为对象使用就可以调用其所有属性和方法。
10. 正则表达式(RegExp)
10.1. JS使用方法
- 直接量语法(Perl风格的语法)
/pattern/attributes - 创建 RegExp 对象的语法:
new RegExp(pattern, attributes); - 参数说明:
- pattern 是一个字符串,称为模式字符串,指定了正则表达式的模式或其他正则表达式。
- attributes 是一个可选的字符串,指定了额外的处理指令。
- 包含属性 “g”、“i” 和 “m”,分别用于指定全局匹配、区分大小写的匹配和多行匹配。
10.2. 使用RegExp对象
test() 方法
var v = "aaacatbbbcat";
var reCat = /cat/; // 创建正则表达式对象
// test()方法:如果字符串中包含指定正则表达式模式就返回 true。
document.write("regCat.test(v):" + reCat.test(v) + "<br/>"); // true
exec() 方法
var v = "aaacatbbbcat";
var reCat = new RegExp("cat"); // 创建正则表达式对象。用上面双斜杠简单
// exec()方法:只返回第一个匹配项。
document.write("reCat.eval(v):" + reCat.exec(v)) // cat(只出现一次,为什么?)
10.3. 扩展的字符串方法
match() 方法
返回一个包含在字符串中的所有匹配的数组。(非全局匹配只返回一个,全局:所有)
replace()方法
替换字符串中的某一部分。它可以用另一个字符串(第二个参数)来替换某个子串(第一个参数)的所有匹配。
第一个子串(被替换的子串)可以用正则表达式表示。这样符合正则表达式的子串将全部被替换。
search()方法(返回第一次出现的位置,是一个数字)
Search()方法与indexOf()方法有些类似,但是它使用一个RegExp对象而非一个子字符串。Search()方法返回在字符串中出现的第一个匹配的位置。全局匹配正则表达式(带参数g)在使用search()方法时不起作用。
split()方法
将字符串分割成一系列子串并通过一个数组返回。
例子:
var str = "abcdefg10higkl30mnop888qefgo";
document.write("str:" + str + "<br/>");
document.write("str.match(/\d+/g):" + str.match(/\d+/g) + "<br/>"); // g:全局匹配,没有g只匹配一个
document.write("str.replace(/\d+/g):" + str.replace(/\d+/g, '@') + "<br/>");
document.write("str.search(/\d+/g):" + str.search(/\d+/g) + "<br/>");
document.write("str.split(/\d+/g):" + str.split(/\d+/g) + "<br/>");
10.4. 正则表达式语法
10.5. 反向引用
反向引用是针对分组的技术。反向引用是获得正则表达式中某个分组匹配到的值。
// 反向引用
var sToMatch = "#123456aaa$789";
var reNumbers = /#(\d+([a-z]*(\$)))/;
alert(reNumbers.test(sToMatch));
// 分组:几个()几个分组
document.write("<br/>RegExp.$1:" + RegExp.$1); // 最外面的括号
document.write("<br/>RegExp.$2:" + RegExp.$2); // ([a-z]*(\$))
document.write("<br/>RegExp.$3:" + RegExp.$3); // (\$)