javascript权威指南学习笔记 (2)...........
javascript权威指南学习笔记 (2)...........七.类、构造函数、原型
Math类
方法:
random 前开后开,取0-1之间伪随机数
ceil前开后闭,对一个数进行上舍入
floor 前闭后开,对一个数进行下舍入
round就近取整
max 最大值
min 最小值
String类
对象创建:
new String("Hi")
Stinrg("Hi")
"Hi"
方法:
indexOf检索字符串
lastIndexOf从后向前检索字符串
1、字符位置是从0开始索引
2、即使是从后往前查找,返回位置时也还是位置0开始计算
3、当在字符串中索引不到该子串时,返回-1值。
charAt返回在指定位置的字符
charCodeAt返回在指定位置的字符的Unicode编码
slice(a[,b])截取字符串
substring(a[,b])取子串
substr(a[,length])取子串
slice和substr,当a为负数从字符串尾部开始计算
substring为负数从0开始计算
match 在字符串中检索指定的值,返回匹配结果的数组
search 检索指定的子字符串,返回相匹配的子串起始位置,没有匹配返回-1
toLowerCase转小写
toUpperCase转大写
实例化obj对象三步:
------------------------------------------function A(x){
this.x = x;
}
var obj = new A(1); ------------------------------------------
1.创建obj对象:obj = new Object();
2.将obj的内部_proto_指向构造他的函数A的prototype,同时obj.constructor===A.prototype.constructor
3.将obj作为this去调用构造函数A,初始化
区分继承属性和常规属性的方法:
Object.hasOwnProperty()
在原型对像中定义方法,对象中都可以用,原型对象的endsWith方法是唯一的副本共享,每个对象不创建单独副本。
String.prototype.endsWith = function(c){}
绝对不能在Object.prototype添加属性,因为添加的属性可以用for/in循环枚举,而{}对象没有可枚举属性,在对象用作关联数组代码会出错。
要在js中定义一个类方法只要让相应的函数成为构造函数的一个属性。
--------------------------------------------function Circle(radius){
this.r = radius;
}
Circle.max = function(a,b){};
Circle.max(c,d); --------------------------------------------
一个类的属性声明为私有的可以使用闭包。
--------------------------------------------function f(a,b){
this.a = function(){return a;}
this.b = function(){return b;}
} --------------------------------------------
typeof null--object
typeof undefined -- undefined
typeof 数组-- object
typeof 函数-- function 原型eg1:
------------------------------------------------1function A(x){
2 this.x = x;
3}
4A.prototype.a = "a";
5function B(x,y){
6 this.y = y;
7 A.call(this,x);
8}
9B.prototype.b1 = function(){
10 alert("b1");
11}
12B.prototype = new A();
13B.prototype.b2 = function(){
14 alert("b2");
15}
16B.prototype.constructor = B;
17var obj = new B(1,3); ------------------------------------------------
这个例子讲的就是B继承A。第7行类继承:A.call(this.x);。实现原型继承的是第12行:B.prototype = new A();
就是说把B的原型指向了A的1个实例对象,这个实例对象具有x属性,为undefined,还具有a属性,值为"a"。所以B原型也具有了这2个属性(或者说,B和A建立了原型链,
B是A的下级)。而因为方才的类继承,B的实例对象也具有了x属性,也就是说obj对象有2个同名的x属性,此时原型属性x要让位于实例对象属性x,所以obj.x是1,
而非undefined。第13行又定义了原型方法b2,所以B原型也具有了b2。虽然第9~11行设置了原型方法b1,但是你会发现第12行执行后,B原型不再具有b1方法,
也就是obj.b1是undefined。因为第12行使得B原型指向改变,原来具有b1的原型对象被抛弃,自然就没有b1了。
第12行执行完后,B原型(B.prototype)指向了A的实例对象,而A的实例对象的构造器是构造函数A,
所以B.prototype.constructor就是构造对象A了(换句话说,A构造了B的原型)。
alert(B.prototype.constructor)出来后就是"function A(x){...}" 。同样地,obj.constructor也是A构造对象,alert(obj.constructor)出来后就是"function A(x){...}" ,
也就是说B.prototype.constructor===obj.constructor(true),但是B.prototype===obj.constructor.prototype(false),因为前者是B的原型,具有成员:x,a,b2,
后者是A的原型,具有成员:a。如何修正这个问题呢,就在第16行,将B原型的构造器重新指向了B构造函数,那么B.prototype===obj.constructor.prototype(true),
都具有成员:x,a,b2。
如果没有第16行,那是不是obj = new B(1,3)会去调用A构造函数实例化呢?答案是否定的,你会发现obj.y=3,所以仍然是调用的B构造函数实例化的。
虽然obj.constructor===A(true),但是对于new B()的行为来说,执行了上面所说的通过构造函数创建实例对象的3个步骤,第一步,创建空对象;第二步,
obj.__proto__ === B.prototype,B.prototype是具有x,a,b2成员的,obj.constructor指向了B.prototype.constructor,即构造函数A;
第三步,调用的构造函数B去设置和初始化成员,具有了属性x,y。虽然不加16行不影响obj的属性,但如上一段说,却影响obj.constructor和obj.constructor.prototype。
所以在使用了原型继承后,要进行修正的操作。
关于第12、16行,总言之,第12行使得B原型继承了A的原型对象的所有成员,但是也使得B的实例对象的构造器的原型指向了A原型,所以要通过第16行修正这个缺陷。
原型eg2:
--------------------------------------------------------function Foo() {
this.value = 42;
}
Foo.prototype = {
method: function() {}
};
function Bar() {}
// 设置Bar的prototype属性为Foo的实例对象
Bar.prototype = new Foo();
Bar.prototype.foo = 'Hello World';
// 修正Bar.prototype.constructor为Bar本身
Bar.prototype.constructor = Bar;
var test = new Bar() // 创建Bar的一个新实例 ---------------------------------------------------------
// 原型链test
Bar.prototype
{ foo: 'Hello World' }
Foo.prototype
{method: ...};
Object.prototype
{toString: ... /* etc. */}; ---------------------------------------------------------
test 对象从 Bar.prototype 和 Foo.prototype 继承下来;因此,
它能访问 Foo 的原型方法 method。同时,它也能够访问那个定义在原型上的 Foo 实例属性 value。
需要注意的是 new Bar() 不会创造出一个新的 Foo 实例,而是 重复使用它原型上的那个实例;
因此,所有的 Bar 实例都会共享相同的 value 属性。
注意: 不要使用 Bar.prototype = Foo,因为这不会执行 Foo 的原型,
而是指向函数 Foo。 因此原型链将会回溯到 Function.prototype 而不是 Foo.prototype,
因此 method 将不会在 Bar 的原型链上。
当查找一个对象的属性时,js会向上遍历原型链,直到顶层没找到就返回undefined。
要提防原型链过长带来的性能问题,并知道如何通过缩短原型链来提高性能。
更进一步,绝对不要扩展内置类型的原型,除非是为了和新的 JavaScript 引擎兼容。
js两个小括号()()连用:函数会被立即执行
---------------------------------------(function(){alert("aaa");})();
function foo(){alert(1);}foo(); ---------------------------------------
hasOwnProperty函数判断对象是否包含自定义属性而不是原型链上的属性。
如果hasOwnProperty被非法占用。可以用外部的hasOwnProperty函数获取
{}.hasOwnProperty.call(foo,'bar');
for in 循环不会遍历那些 enumerable 设置为 false 的属性;比如数组的 length 属性。
八.模块和名字空间
当定义一个全局变量时,有被其他模块覆盖的危险,为了避免定义全局变量,使用模块化编程。
---------------------------------------------var ModuleClass={};
ModuleClass.函数名1 = function(){
};
ModuleClass.函数名2 = function(){
}; ---------------------------------------------
使用ModuleClass对象作为名字空间,将所有函数变量以及函数都放入其中。
如果名字冲突,可以使用域的方式做多级域名
---------------------------------------------var util;
if(!util)util={};
util.ModuleClass = {};
util.ModuleClass.函数名1 = function(){
};
util.ModuleClass.函数名2 = function(){
};
--------------------------------------------- 九.正则表达式
正则表达式方法:
test()
检测指定的字符串是否存在,返回true或false
exec()
查找匹配
匹配失败返回null
匹配成功返回一个数组,数组的0元素包含完整的匹配,其他元素包含的是匹配中任意一个子匹配,并更新RegExp对象属性
index是匹配发生的字符位置,input是被检索的字符串
String方法
search()
指明是否存在相应匹配,成功返回第一个成功检索位置,失败返回-1
replace()
替换字符串,返回替换后的字符串
split()
分割字符串,返回分割数组
match()
如果没有找到匹配返回null,否则返回一个数组
RegExp的方法test()和exec()受全局标志"g"和lastIndex的影响,而string的方法match(),search()等则不受影响
在一次匹配成功后,会设置lastIndex,下一次匹配,就会从这个lastindex所指示的位置开始尝试匹配,
当匹配失败时,lastIndex会被重新置为0
---------------------------------------------------------------------var arr = ;
var reg = /^\d+$/g;
for(var i = 0;i<arr.length;i++){
document.write("源字符串:"+arr+" 验证结果:"+reg.test(arr)+" lastindex:"+reg.lastIndex+"<br/>");
}
document.write("<br>");
var reg = /^\d+$/;
for(var j = 0;j<arr.length;j++){
document.write("源字符串:"+arr+" 验证结果:"+reg.test(arr)+" lastindex:"+reg.lastIndex+"<br/>");
} 结果:
源字符串:1 验证结果:true lastindex:1
源字符串:2 验证结果:false lastindex:0
源字符串:3 验证结果:true lastindex:1
源字符串:4 验证结果:false lastindex:0
源字符串:5 验证结果:true lastindex:1
源字符串:1 验证结果:true lastindex:1
源字符串:2 验证结果:true lastindex:1
源字符串:3 验证结果:true lastindex:1
源字符串:4 验证结果:true lastindex:1
源字符串:5 验证结果:true lastindex:1
---------------------------------------------------------------------
[\u4e00-\u9fa5]匹配任意一个汉字
\s 任意空白字符(\r\n\f\t\v)
\b单词边界
. 匹配除\n以外的字符,匹配所有字符一般用[\s\S]或.加(?s)匹配模式
?s Single-line模式
用new RegExp()创建的正则要注意引号内的转义
js只支持顺序环视,不支持逆序环视。java中支持顺序环视和确定长度表达式的逆序环视。
0-100的数字
^(?|100)$
捕获组
普通捕获组()/命名捕获组(?<name>(Expression))
非捕获组
(?:Expression)
消除一些不得不使用(),却又不需要使用捕获组而带来内存被占用,匹配效率降低的情况。
环视
匹配内容不计入最终匹配结果,零宽度[(?=Expression),(?<=Expression)]
----------------------------------------------------------------------var str = "aa<p>one</p>bb<div>two</div>cc";
var reg = /<(?!\/?p\b)[^>]+>/;
alert(str.match(reg)); //div ----------------------------------------------------------------------
匹配优先[贪婪模式]({m},{m,n},{m},?,*,+)/忽略优先[非贪婪模式]({m}?,{m,n}?,{m,}?,??,*?,+?)
在匹配成功的情况下,贪婪模式进行了更少的回溯,回溯过程需要进行控制权的交接
反向引用
捕获组在匹配成功时,会将子表达式匹配到的内容,保存到内存中一个以数字编号的组里,可以通过反向引用方式,引用这个局部变量的值\1/\k<name>
年份0001-9999,格式yyyy-MM-dd或yyyy-M-d
^(?:(?!0000){4}([-/.]?)(?:(?:0?|1)\1(?:0?|1|2)|(?:0?|1)\1(?:29|30)|
(?:0?|1)\1(?:31))|(?:{2}(?:0||)|(?:0||)00)
([-/.]?)0?2\2(?:29))$
取img中的属性。
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
var data = [' <img alt="" border="0" name="g6-o44-1" onload="DrawImage" src="/bmp/foo1.jpg" />', ' <img src="/bmp/foo2.jpg" alt="" border="0" name="g6-o44-2" onload="DrawImage" />'] ;
var reg = /<img\b(?=(?:(?!name=).)*name=(['"]?)([^'"\s>]+)\1)(?:(?!src=).)*src=(['"]?)([^'"\s>]+)\3[^>]*>/i;
for(var i=0;i<data.length;i++)
{
var s = data;
document.getElementById("result").value += "源字符串:" + s + "\n";
document.write("<br />");
if(reg.test(s))
{
document.getElementById("result").value += "name: " + RegExp.$2 + "\n";
document.getElementById("result").value += "src: " + RegExp.$4 + "\n";
}
}
Results:
源字符串: <img alt="" border="0" name="g6-o44-1" onload="DrawImage" src="/bmp/foo1.jpg" />
name: g6-o44-1
src: /bmp/foo1.jpg
源字符串: <img src="/bmp/foo2.jpg" alt="" border="0" name="g6-o44-2" onload="DrawImage" />
name: g6-o44-2
src: /bmp/foo2.jpg ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------<html>
<head>
</head>
<body>
<script type="text/javascript">
var s = " f e r r y";
alert("s="+s.replace(/\s*/g,"")+"!");//去所有空格
alert("s="+s.replace(/^\s*/g,"")+"!"); //去左空格
alert("s="+s.replace(/\s*$/g,"")+"!"); //去右空格
alert("s="+s.replace(/^\s*|\s*$/g,"")+"!"); //去左右空格
</script>
</body>
</html>
页:
[1]