javascript权威指南学习笔记

一.数据类型:

js中,所有的数字都是浮点型的。

isNaN()/isFinite() //检测数据类型

Infinity //无穷大

Number.MAX_VALUE //可表示的最大数字

Number.MIN_VALUE //可表示的最小数字

数字转字符串

n+""

String(N)

n.toString() //可以加参数 2-2进制 8-8进制 16-16进制

n.toFixed() //显示小数点后的指定位数

n.toExponential() //指数表示

n.toPrecision() //指定有意思的位数

字符串转数字

+字符串

parseInt(string,16) //截取整数,支持另一个参数指定解析的数字基数(2-36)

parseFloat() //截取整数和浮点数

布尔类型转换

1.布尔转其他

true-1 true-"true"

false-0 false-"false"

2.其他转布尔

数字 0/NaN-false 其他-true

字符串 空字符串-false 其他-true

对象 空值/未定义的值-false 非空对象、数组、函数-true

3.显示转换

Boolean(x)/!!x

null的转换

布尔 null-false

数字 null-0

字符串 null-"null"

undefined的转换

布尔 undefined-false

数字 undefined-NaN

字符串 undefined-"undefined"

date类型转换/格式化

date -- string

date.toGMTString()

date.toLocaleString()

string -- date

new Date(s)

string -- string

var date = new Date(s)

date.toLocaleString()

===等同

数值和string只要值相等就完全相等。

两个值同为null或undefined就完全相等。

只要有一个为NaN就不完全相等。

引用同一个对象、数组或函数就完全相等。

==相等

同类型数据比较,相等就相等。

不同类型数据比较,先转换成同类型数据再比较。

null和undefined相等。

二.变量

未用var声明的变量会被创建为全局变量。

js中没有块级作用域,函数中声明的所有变量在函数内都有定义。

----------------------------------------------

function test(){

for(var k=0;k<10;k++){

alert(k);

}

alert(k); //10

}

----------------------------------------------

js解释器运行时先创建一个全局对象,对象的属性就是js程序的全局变量。

js函数都运行在自己独有的执行环境。具有自己的调用对象。调用的对象的属性就是该函数的局部变量。

三.运算符

in

要求左边是字符串或可以被转换成字符串,右边是数组或函数。

delete

var声明的变量不能删除,当delete操作的不是属性、数组元素或变量时返回true

------------------------------------------

delete 1; //true

delete x; //true

------------------------------------------

void

舍弃运算数的值,返回undefined,常用在客户端的javascript:URl中,计算表达式的值,而浏览器不会显示这个值。

另一个用途是专门生成undefined值。undefined是在javascript1.5中实现,考虑向后兼容,用void 0比undefined更有用。

<a href="javascript:void window.open();">Open New Window</a>

a href="javascript:void(0)"

如果是个# ,就会出现跳到顶部的情况,:个人收藏的几种方法:

1:<a href="####"></a>

2:<a href="javascript:void(0)"></a>

3:<a href="javascript:void(null)"></a>

4:<a href="#" onclick="return false"></a>

5:<span ></span>(在FF中不能显示)

方法2和3有可能导致页面中的GIF动画停止播放,推荐使用方法4

,运算符

先计算左边的参数,再计算右边的参数,然后返回右边参数的值

undefined不是保留字,为了确保其值不被改变,可以声明一个未赋值的变量

--------------------------------------------

var undefined; //undefined为undefined

--------------------------------------------

未声明的变量alert会报error错,typeof会返回undefined

null与undefined关系

undefined实际是null派生的,两者相等

var t1 = 56;

var t2 = 070;

var t3 = 0x38;

alert(t1==t2); //output:true

alert(t2==t3); //output:true

这说明无论是8进制、16进制,其变量都保存的是10进制的值。

数值运算优先调用valueOf,字符串或输出运算优先调用toString.

四.语句

switch语句

匹配case表达式是用===等同运算符判断的,所以表达式必须在没有类型转换的情况下进行。

for/in语句

for(variable in object)

statement

with语句(代码很难优化,运行速度慢,不建议使用)

with语句用于暂时修改作用域链

with(object)

statement

这条语句将object添加到作用域链的头部,然后执行statement,在把作用域链恢复到原始状态。

五.对象和数组

对象创建:

----------------------------------------------------

var obj = {};

var obj = new Object();

----------------------------------------------------

遍历对象:

----------------------------------------------------

for(var name in o) statement

----------------------------------------------------

检测属性的存在:

----------------------------------------------------

if("x" in o)

if(o.x !==undefined)

//区别当一个属性定义为o.x=undefined时,上一个有操作,后一个不做任何操作。

----------------------------------------------------

删除属性:

----------------------------------------------------

delete o.xxx

----------------------------------------------------

删除操作将属性从对象中移除,for/in不会枚举该属性。

Object的constructor属性

每个对象都有一个constructor属性,他引用初始化之个对象的构造函数。

----------------------------------------------------------------------------------------------------

if((type o == "object")&&(o.constructor == Date)) //确定一个位置值的类型。

if((type o == "object")&&(o instanceof Date)) //instanceof检查constructor属性的值。

----------------------------------------------------------------------------------------------------

检测对象的一个属性是不是非继承属性

----------------------------------------------------

o.hasOwnProperty("a");

----------------------------------------------------

检测一个对象的类型强烈建议使用Object.property.toString方法。

typeof只使用在检测一个变量是否已经定义。

----------------------------------------------------

Object.prototype.toString.call([]) //"[object Array]"

typeof foo !== 'undefined'

----------------------------------------------------

instanceof 操作符用来比较两个操作数的构造函数。只有在比较自定义的对象时才有意义。

如果用来比较内置类型,将会和 typeof 操作符 一样用处不大。应该仅仅用来比较来自同一个 JavaScript 上下文的自定义对象

数组:

Array对象的创建

1.new Array(10)

2.new Array("1","2")

3.["1","2"]

js中数组是稀疏的,所以数组的下标不必落在一个连续的数字范围

-------------------------------------------

a[0] = 1;

a[10000] = 10000;

//js解释器只给下标为0和10000的元素分配内存

-------------------------------------------

遍历数组:

js中数组是对象,用for in循环会枚举原型链上所有属性,过滤属性的方式是用hasOwnProperty函数,会比普通的for慢。

推荐使用经典的for循环,通过l=list.length来缓存数组的长度。

---------------------------------------

var list = [1,2,3,4,......10000000000];

for(var i=0;l=list.length;i<l;i++){

alert(i);

}

---------------------------------------

delete操作和对对象的操作不同,对数组操作元素设置为undefined ,元素本身还存在

数组方法:

join()

把数组中所有元素转换成字符串

----------------------------------------

var array = [1,2,3];

alert(array.join("|")); //1|2|3

----------------------------------------

reverse()

颠倒数组元素的顺序。 --改变原数组

sort()

排序 默认是按字母顺序。

a.sort(function(a,b){

return a-b;

}); --改变原数组

concat()

数组连接。如果参数是数组将被展开连接,但不支持递归的展开。 --不改变原数组

---------------------------------------------------------------

var a = [1,2,3];

alert(a.concat(4,[5,[6,7]])); //[1,2,3,4,5,[6,7]]

---------------------------------------------------------------

slice()

截数组。第一个参数是起始位置,第二个参数是结束位置。参数为负则相对于数组最后一个元素。 --不改变原数组

---------------------------------------------------------------

var a = [1,2,3,4,5];

alert(a.slice(1,-1)); //[2,3,4]

---------------------------------------------------------------

splice()

插入或删除数组元素。第一个参数是插入或删除元素的位置,第二个参数是删除的个数,后面元素是插入的元素。 --改变原数组

---------------------------------------------------------------

var a = [1,2,3,4,5]; //Returns [3,4]

alert(a.splice(2,2,[1,2],3)); //a=[1,2,[1,2],3,5]

---------------------------------------------------------------

push()/pop()

从数组的尾部添加或删除元素。返回数组新长度。

unshift()/shift()

从数组的头部添加或删除元素。返回数组新长度。

toStirng()/valueOf

每个数组元素调用toString()然后用","连接.

六.函数

函数定义

function square(x){ return x*x;}

var square = function(x) { return x*x;}

var square = new Functioin("x","return x*x;");

函数参数

js函数可以以任意数目的参数来调用,而不管函数定义中的参数个数

函数中判断一个参数是否传进来

---------------------------------------------

if(!a) a=[];

a=a||[];

---------------------------------------------

arguments对象;

实际传的参数列表,类似数组功能,有数组下标属性和length属性

arguments对象为其内部属性以及函数形式参数创建getter和setter方法。

改变形参的值会影响到arguments对象的值,反之亦然。

-------------------------------------------

function foo(a,b,c){

arguments[0] = 2;

a; //2

b=4;

arguments[1]; //4

var d = c;

d = 9;

c; //3

}

foo(1,2,3);

-------------------------------------------

arguments是java标识符避免同名变量

callee属性:

引用当前正在执行的函数,可以用作对未命名函数递归调用

--------------------------------------------

function(x){

if(x<=1) return 1;

return x*arguments.callee(x-1);

}

--------------------------------------------

length属性:

定义函数的实际参数数

prototype属性:

每个函数都有一个prototype属性,它引用的是预定义的原型对象。

call和apply方法:

第一个参数是要调用函数的对象,后面参数是函数的参数。

apply传递给函数的参数是由数组指定。

Function构造函数:

最后一个参数是函数体,如果前面有参数是函数参数

闭包:

定义在函数内部的函数:

用于读取函数的局部变量,

函数返回局部变量

让这些变量的值始终保持在内存中

调用闭包的变量声明为全局变量。

当一个函数作为函数而不是方法来调用的时候,this指向的是全局对象

--------------------------------------------------------------

var name = "ferry_passion";

var obj = {

"name":"ferry",

getName:function(){

alert(this.name); //ferry

return function(){

return this.name;

}

}

};

alert(obj.learn()()); //ferry_passion

--------------------------------------------------------------

七.类、构造函数、原型

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:

------------------------------------------------

1 function A(x){

2   this.x = x;

3 }

4 A.prototype.a = "a";

5 function B(x,y){

6   this.y = y;

7   A.call(this,x);

8 }

9 B.prototype.b1 = function(){

10   alert("b1");

11 }

12 B.prototype = new A();

13 B.prototype.b2 = function(){

14   alert("b2");

15 }

16 B.prototype.constructor = B;

17 var 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的实例]

Bar.prototype [Foo的实例]

{ 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 = [1,2,3,4,5];

var reg = /^\d+$/g;

for(var i = 0;i<arr.length;i++){

document.write("源字符串:"+arr[i]+" 验证结果:"+reg.test(arr[i])+" lastindex:"+reg.lastIndex+"<br/>");

}

document.write("<br>");

var reg = /^\d+$/;

for(var j = 0;j<arr.length;j++){

document.write("源字符串:"+arr[j]+" 验证结果:"+reg.test(arr[j])+" 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的数字

^([1-9]?[0-9]|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)[0-9]{4}([-/.]?)(?:(?:0?[1-9]|1[0-2])\1(?:0?[1-9]|1[0-9]|2[0-8])|(?:0?[13-9]|1[0-2])\1(?:29|30)|

(?:0?[13578]|1[02])\1(?:31))|(?:[0-9]{2}(?:0[48]|[2468][048]|[13579][26])|(?:0[48]|[2468][048]|[13579][26])00)

([-/.]?)0?2\2(?:29))$

取img中的属性。

---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

var data = [' <img alt="" name="g6-o44-1" onload="DrawImage" src="/bmp/foo1.jpg" />', ' <img src="/bmp/foo2.jpg" alt="" 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[i];

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="" name="g6-o44-1" onload="DrawImage" src="/bmp/foo1.jpg" />

name: g6-o44-1

src: /bmp/foo1.jpg

源字符串: <img src="/bmp/foo2.jpg" alt="" 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>