javascript学习总结
1 运算符与表达式:
运算符:
包装对象:数值,字符串,布尔值在给增加属性时会自动创建一个临时对象,即包装对象,而包装对象是只读的,其增加的属性并不会保存下
来。可以通过String(),Number(),Boolean()构造函数显示创造包装对象。对数值,字符串,布尔值调用方法时也会自动创建一个临时对象,即包装对
象,在用完后会自动销毁。
----undefined,null,布尔值,数值,字符串比较的是值。两个单独的对象或数组永不相等。因为对象和数组比较的是引用,其他比较的是值。
----
== 在判断两个值是否相等时可以做类型转换,而 === 在判断时不做类型转换。假值是false,null,undefined,0,-0,NaN,"",所有的其他值包括所有对象都是真值。
----
全局对象:
全局属性(比如undefined,Infinity和NaN),
全局函数(比如:isNaN(), parseInt(), eval()),
构造函数:(比如:Date(), RegExp(), String(), Object(), Array()),
全局对象:(比如:Math和JSON)
----在全局作用域下声明变量可以不写 var,但声明局部变量(在函数体内)则必须使用var语句,否则,将会当作全局变量处理。使用var声明的变
量是不可删除的,而未声明的变量赋值创建的全局变量是可以删除的。
----声明提前:javascript函数体内声明的所有变量(但不涉及赋值)都被“提前”至函数体的顶部,变量在声明之前已经可用。
常用运算符:
in运算符:in运算符希望它的左操作数是一个字符串或可以转换为字符串,希望它的右操作数是一个对象。如果右侧的对象拥有一个名为左操作
数的属性名,那么表达式返回true。
instanceof运算符:instanceof运算符希望左操作数是一个对象,右操作数标识对象的类。如果左侧的对象是右侧类的实例,则表达式返回
true,否则返回false,如果
instanceof左操作数不是对象,返回false,如果右操作数不是函数,则抛出类型错误异常。
typeof运算符:返回操作数的类型:undefined:“undefined”,null:"object",true或false:"boolean",任意数字或NaN:"number",任意字符
串:“string”,任意函数:“function”,任意内置对象(非函数):“object”,任意宿主对象:由编译器各自实现的字符串,但不
是“undefined”,“boolean”,“number”,“string”
delete运算符:删除对象的属性或者数组元素。用它来做删除操作的,不是用来返回一个值的。用户通过var声明的属性不能删除。用户通过
function语句定义的函数和函数参数也是不能删除的。但可以删除其属性和元素。
void运算符:出现在操作数之前,操作数会照常计算,但忽略计算结果并返回undefined。
函数声明语句和函数定义表达式:
1函数声明语句: var f = function fact(x){return x+1;}//函数的名称(可省略)可用于函数的递归调用。
2函数定义表达式: function f(x){return x+1;}//适用于在赋值和调用过程中的函数定义,(如果有名称:将称为定义该函数的函数内部
的一个局部变量。)通常不需要名称,适合用来定义只会用到一次的函数。
函数声明和定义语句通常出现在js代码的最顶层,也可以嵌套在其他函数体内,但在嵌套时,函数声明只能出现在所嵌套函数
的顶部,也就是说,函数定义不能出现在if语句,while语句或其他任何语句中。
这两种声明方式的区别:
函数声明(语句)通过var = function(不能加函数名,否则不能提前。):和通过var声明变量一样,只有变量声明提前了,变量
的初始化代码仍然在原来的位置。
然而通过var声明函数的话,函数名称和函数体均提前了。不能出现在循环,条件判断,try/catch/finally以及with语句中。函数定义
(表达式):不会被提前。可以出现在任何地方。
语句:
for/in语句:for(variable in object) statement :遍历一个对象的属性。将对象object中的各个属性名赋值给变量variable,如果
是数组则遍历索引。内置的方法是不可遍
历的。自定义的方法和属性是可遍历的。通过继承获得的属性也是可遍历的。
with语句:with(object)statement 将object所表示的对象当成statement语句的作用域,然后执行statement,最后把作用域
链恢复到原始状态。
----
3 对象:
概念:属性的无序集合,每个属性都是一个名/值对,除了可以保持自有的属性,javascript对象还可以从一个称为原型的对象
继承属性。除了字符串,数字,true,false,null,undefined(和不可变对象非常相似),其他的值都是对象。
三类对象:
内置对象:是由ECMAScript规范定义的对象或类。例如:数组,函数,日期,正则表达式。
宿主对象:是由javascript解释器所嵌入的宿主环境(比如web浏览器)定义的。
自定义对象:是由运行时的javascript代码创建的对象。
两类属性:
自有属性:是直接在对象中定义的属性。
继承属性:是在对象的原型中定义的属性。f.prototype = p (p是一个对象,f构造函数继承了p的属性和方法。通过new
f()可以创建f的对象。)
对象的创建:可以通过对象直接量,关键字new,Object.create()函数来创建对象。
对象直接量:由若干个名值对组成的映射表,名值对之间用逗号分隔,名和值用冒号分隔,外面用花括号括起来。属性值可以
是任意类型的javascript表达式,表达式的值,(可以是原始值,也可以是对象的属性的值)。所有通过对象直接量创建的对象都具有同一个原型对
象,可以通过Object.prototype获得对原型对象的引用
new创建对象:new运算符创建并初始化一个新对象,关键字new后跟一个构造函数,构造函数用以初始化一个新创建的对
象,原始类型(如:Object({}),Date,Array([]),RegExp)都包含内置的构造函数。用户自定义的构造函数来初始化对象也是非常
常见的。通过new和构造函数创建的对象的原型是构造函数的prototype属性的值。
原型:没有原型的对象为数不多,Object.prototype,其他原型对象都是普通对象,普通对象 都具有原(Object.prototype),
创建对象:Object.create(),可以通过任意原型创建新对象。第一个参数是对象的原型,第二个参数可选对对象的属性的描述。如:
var o1= Object.create({x:1,y:3});
var o2= Object.create(null)=>>不继承任何属性和方法
var o3= Object.create(Object.prototype);==>和new Object()和{}一样。
属性的查询与设置:
查询:如:var author = book.author;//得到book的“author”属性。 也可以:var author = book["author"];
设置:如:book.edition = 5;
两者的区别:(.)操作符使用静态的标识符,必须写死在程序中。而([])使用动态的字符串值,可以在运行是更改。如果对
象已有属性,则改变这个已有的属性,如果不存在这个属性,则对象增加这个属性,如果继承,则被同名的属性覆盖。
继承:假设要查找对象o的属性,如果o中不存在,会在o的原型对象中查询属性,如果还没有,会在这个原型对象的原型中查
找,直到找到属性或者原型为null的对象为止。这就是原型链。通过这个链实现属性的继承。通过方法var c= inherit(对象变量a或对
象);可使c对象继承a对象的属性和方法,注:它总是在原始对象上创建属性或对已有的属性赋值,而不会去修改原型链上的属性,
只有在查询属性时才会去原型链上查找,而设置属性与继承无关。
删除属性:delete运算符可以删除对象的属性。它的操作数应当是一个属性访问表达式。如:delete book["main title"];只能删
除自有属性,不能删除继承属性。要删除继承属性必须从定义这个属性的原型对象上删除它。
检测属性:in操作副:in操作副左侧是属性名,右侧是对象。 对象的hasOwnProperty()方法用来检测给定的名字是否是对象的
自有属性,如:o.hasOwnProperty("x");//检测对象o的x属性是否是自有属性。 propertyIsEnumerable()方法只有检测到是自有属性且
这个属性的可枚举性为true时才返回true。 还可以使用(!==)判断一个属性是否是undefined。
枚举属性:for/in循环可以在循环体中遍历对象中的所有可枚举属性(包括自有属性和继承属性)。把属性名称赋值给循环变
量。对象继承的内置方法是不可枚举的。 Object.keys():返回一个数组,这个数组由对象中的可枚举的自有属性的名称组成。
Object.getOwnPropertyNames():返回对象的所有自有属性的名称,而不仅仅是可枚举的属性。
存储器属性:由getter和setter定义的属性。getter属性返回属性存取表达式的值,setter负责设置数据属性的值。和数据属性不
同,存储器属性不具有可写性。存储器属性可以继承。
属性的特征:即可写,可枚举和可配置的特性。
对象的三个属性:
原型属性:是用来继承属性的,原型对象在实例创建之初就建立好了。将对象作为参数传入Object(原型对
象).getPrototypeOf(对象)可以查询它的的原型。对象可以使用o.constructor.prototype来检测一个对象的原型。通过new表达式创建
的对象,通常继承一个constructor属性,这个属性指代创建这个对象的构造函数。对于用Object。create()创建的对象的
constructor.prototype都是Object()的构造函数。
_proto_属性:用以直接查询/设置对象的原型,但不推荐使用,因为很多浏览器不支持。
类属性:是一个字符串,用以表示对象的类型信息。没有设置这个属性的方法,只有间接的查询它。默认的toString()返
回如下形式的字符串:[object class](继承自Object),可以如下获得类的字符串:Object.prototype.toString.call(o).slice(8,-1);对象直接
量,Object.create和自定义传见的对象的类属性都是Object。
可扩展性:表示是否可以给对象增加新属性,所有的内置对象和自定义对象都是可扩展的,函数Object.esExtensible()
来判断该对象是否是可扩展的。可以用函数:Object.preventExtensions()将对象转换为不可扩展的,一旦转换为不可扩展,就无法转
换为可扩展的。
4 数组:
创建数组:
数组直接量:在方括号中将数组元素用逗号隔开即可,值不一定是直接量,也可以是任意的表达式。也可以包含对象直接
量或其他数组直接量。如果省略某个值,省略的元素将被赋予undefined
构造函数:
1调用时没有参数,如:var a=new Array();等同于([])
2调用时指定长度,如:var a=new Array(10); 显式指定两个或多个数组元素或数组的一个非数值元素,如:var
a=new Array(3,2,4,"testing","testing");
数组元素的读和写:所有的数组都是对象,可以为其创建任意名字的属性,当数组使用非负整数(可以经过类型转换成非负整
数)时,属性名将当成索引对待,效率变高。如果使用的属性是索引,数组将维护其length属性值。当查询不存在的属性会得到
undefined,
稀疏数组:包含从0开始的不连续索引的数组。length属性值大于元素的个数。在数组直接量中省略值不会创建稀疏数组,省
略元素其值存在定义为undefined,只能通过如下方式创建:
1 var a=new Array(5);
2 var a=p[];a[1000]=0; 3 var a=[,];
length属性:
一。如果为一个数组元素赋值,它的索引i大于或等于现有数组的长度,length属性的值将设置为i+1.
二。设置length属性为一个小于当前长度的非负整数n时,大于或等于n的元素将从中删除。将length设置为大于当前长
度,不会向数组增加新元素,只是创建一个空的区域。
数组元素的增加和删除:
为新索引赋值,如:var a=[];a[0]="zero";
push()方法:可以在数组末尾增加一个或多个元素。
使用unshify()方法向数组首部插入一个元素,其他元素依次下一位置。
删除:
delete运算符:如:delete a[2];不影响数组长度。 可以设置length属性截断数组。
pop方法:减少长度1并返回被删除的元素。
shift()从头部删除一个元素,各索引减1.
数组遍历:
1for循环
2for/in:循环每次将一个可枚举的属性名(包括数组索引)赋值给循环变量,不存在的索引不会遍历到。还会遍历到从
Array.prototype中继承来的方法。
forEach():按照索引的顺序按个传递给定义的一个函数,如:数组对象.forEach(function(数组元素){元素操作;})
多维数组:用数组的数组来近似。访问数组的数组中的元素:使用两次([]),如:table[row][col]
数组方法:在Array.prototype中定义的操作数组的函数。在Array构造函数上定义了这些方法的静态函数版本,所以可以用
Array.方法名(数组对象,方法参数);调用方法。
或:Array.prototype.方法名.call(调用方法的对象,方法参数);
数组对象.join():将数组中所有元素转换为字符串并链接在一起,有一个可选的参数来分隔各个元素,默认为(,)。
数组对象.reverse():将原先数组逆序转换数组,不创建新数组。
数组对象.sort():将数组中的元素排序并返回排序后的数组。默认按字母表顺序排序。如果包含undefined,排到数组尾
部。可传入一个函数进行比较。
数组对象.concat():连接数组对象的元素和参数对象中的元素或数组元素。
数组对象.slice():返回数组对象的一个子数组,两个参数分别指定新数组起始和结束的索引位置。
数组对象.splice():会修改原始数组,在插入或删除元素后会根据需要增加或减少数组的索引值。第一个参数指定了插入
和删除的起始位置,第二个参数指定了应该
从数组中删除元素的个数(省略则删除起始到结束的额所有元素),返回由删除元素组成的数组,紧随其后的任意个数的参数指定了需
要插入到数组中的元素。
数组对象.push():将数组当作栈使用,push()在数组尾部增加一个或多个元素返回新数组长度。
数组对象.pop():删除数组最后一个元素,减少数组长度并返回它删除的值,
数组对象.unshift():在头部插入一个或多个元素,并将已存在的元素移动到更高索引位置,返回数组新的长度
数组对象.shift():删除第一个元素并将其返回。随后元素下移一个位置。
数组对象.toString()或tolocaleString:将每个元素转换为字符串,并用逗号分隔字符串列表,不输出方括号。ECMAScript5中的数组方法:
大多数方法第一个参数接受一个函数,并对数组的每个元素调用一次该函数。稀疏数组中不存在的元素不调用。调用函数提供3个参数:数
组元素,元素索引,数组本身,通常后两个参数可以忽略。如果数组方法有第二个参数,一般数组方法的第一个参数(即函数)作为第二个参数的this
使用。
数组对象.forEach():为每个元素调用指定的函数,传递的函数作为forEach的第一个参数,函数有3个参数,后两个可忽略。
数组对象.map():将调用数组的每个元素传递给指定的函数,并返回一个数组,它包含该函数的返回值。返回新数组,不修改调用的数组,
数组对象.filter():返回的数组元素是调用的数组的一个子数组,传递的函数用来逻辑判断,返回true或false,如果返回true,则该元素为返
回子数组的成员。filter()会跳过稀疏数组中缺少的元素,返回的数组总是稠密的。
数组对象.every():(所有元素都满足返回true)对数组的逻辑判定,对数组元素应用指定的函数进行判定,返回true或false,当且仅当数组
中所有元素调用判定函数都返回true,它才返回true。
数组对象.some():(存在元素满足返回true)至少有一个元素调用判定函数返回true,就返回true,空数组上erery返回true,some返回
false。
数组对象.reduce():使用指定函数将数组元素进行组合,返回单个值,传递的函数有二个参数,分别指调用的元素的值和reduce()方法的
第二参数的初始值,第二个参数(可选)是传递给函数的初始值。当不指定初始值时将使用数组的第一个元素作为初始值。
数组对象.reduceRight():和reduce()工作原理相同,按照索引从高到低处理数组。
数组对象.indexOf():搜索整个数组具有给定值的元素,返回找到的第一个元素的索引,没有找到就返回-1。第二个参数指定从数组开始搜
索位置的索引。
数组对象.lastIndexOf():反向搜索。
判断是否为数组:Array.isArray(需要判断的未知对象)
作为数组的字符串:数组可以使用charAt() 和([])访问单个字符,但typeof操作符返回string,Array.isArray()返回false。通用的数组方法可以
应用到字符串上(修改原数组的方法除外,因为字符串是只读的),如下调用:Array.prototype.方法名(字符串对象,方法参数);
5 函数:
概念:只定义一次,可以被执行或调用任意次,函数定义包括型参,函数调用提供实参。函数使用实参的值计算返回值,称为该函数调用表达式
的值。
this:指代调用该函数的上下文(调用方法的对象)。
方法:函数作为对象的一个属性。构造函数用于初始化一个新的对象。
函数就是对象:可以吧函数赋值给变量,作为参数传递给其他函数,可以设置属性,调用它们的方法。(所有的这一切都可以在对象上完
成。)。可以嵌套定义函数形成闭包,就可以访问父函数中的任意变量。
return语句:如果函数不包含return,或return不包含与之相关的表达式则返回undefined值。
作为函数:如下方式调用:函数名(实参列表),如:printprops({x:1}); 这种方式的调用在严格模式下this指undefined。而非严格模式为全局
对象,所以这种方式调用函数的函数一般不使用this。
作为方法:如果对象o的m方法定义为一个函数,如:o.m=f;则可以如下调用:o.m(x,y);(或o["m"](x,y); a[0](z)//假设数组a[0]是一个函数)
调用上下文为o对象,在方法体中可以使用this引用。函数将基于一个对象进行操作。
作为构造函数:如:var o =new Object();与var o=new Object;等价(无参时可以省略括号)。 构造函数可以使用this来引用这个新创建的
对象。构造函数通常不使用return,只为了初始化新对象,如果显示返回一个对象,则使用返回的对象,其他情况都返回新创建的对象。
通过它们的call()和apply()方法间接调用:任何函数可以作为任何对象的方法来调用,哪怕这个函数不是那个对象的方法。查看相关api。
函数的形参和实参:
形参:当调用函数的时候传入的实参比函数声明的形参少时,剩下的形参都设置为undefined值。
实参对象:参数对象标识符arguments(是一个类数组对象)是指向实参对象的引用,它也包含length属性。js在省略实参都将是
undefined,多出的参数会自动省略。如果形参没有定义,则实参可以是任意个数。
函数变量:如:var f = function square(){};或:var ff=square; 可以通过f()和square()调用这个函数对象。可以将这个函数变量用作对象的属性,
数组的元素,其他函数的实参传递。
函数(变量)的属性:函数是一个特殊的对象,可以拥有属性,当函数需要一个静态变量时可以定义函数属性。如,将函数当成一个变量或一个数
组(只有在定义函数的上下文环境下给函数属性赋初值才起效果),用于保存上次调用记录的信息。
函数自定义属性:通过函数名.函数变量=值;可以为函数定义变量属性。在函数体内部和外部均可以。定义的属性变量可以在函数体内直接调
用。
作为命名空间的函数:为了防止定义的全局变量污染全局命名空间,可使用局部函数,这样全局变量就成了局部变量了。如:
(function(){//模块代码}());//定义这个函数并立即调用它。
作用域链:如果将局部变量看作是自定义实现对象(函数)的属性的话,每一段全局代码或函数,都有一个与之关联的作用域
链,这个对象(作用域链)定义了这个作用域中的变量,这个作用域链是一个对象列表(这组对象定义了全局作用域中的变量)。
在访问变量时,先查看本地作用域是否有此变量,如果没有则依次向上一级作用域查找直到全局作用域()。每定义的函数都会在
所定义函数创建全局作用域,每次调用函数时都会在所调用函数作用域链上创建对象(活动对象(包含所需的形参,this,本地变量
的值))。函数定义时的作用域链到函数执行时依然有效。
闭包:函数对象可以通过作用域链相互关联起来,函数内部的变量都可以保存在函数作用域内。外部函数将嵌套的函数对象作
为返回值的时候往往会发生这种情况,闭包。
闭包的官方定义:允许使用内部函数(即函数定义和函数表达式位于另一个函数的函数体内),而且,这些内部函数可以访问他
们所在的外部函数中声明的所有局部变量,参数,和声明的其他内部函数,当其中一个这样的内部函数在包含它们的外部函数之外
被调用时,就会形成闭包。即内部函数会在外部函数返回后执行。而当这个内部函数执行时,它仍然必须访问其外部函数的局部变
量,参数以及其他内部函数。这些局部变量,参数和函数声明(最初时)的值是外部函数返回时的值,但也会受到内部函数的影
响。
一个函数在每次返回时所创建的和传入的临时变量和参数就会被垃圾回收而不会被保存,但如果有一个外部引用指向这个函数中的
某个变量或嵌套函数(将函数的某个属性赋值给外部变量,或返回一个嵌套函数的引用赋值给外部变量),则不会将变量绑定对象
从作用域链中删除(在调用这个函数时会创建这个函数的变量绑定对象在作用域链中)。
每个新创建的函数对象都会创建一个新的作用域链和一个新的私有变量,并且彼此包含不同的私有变量。当外部函数返回,其他任
何代码都无法访问私有变量,只有内部的函数
才能访问它。
闭包就是在一个外部函数中返回一个嵌套函数或一个对象的方法,嵌套函数和方法实现对外部函数定义的私有变量的修改。其
他方式无法无法修改私有变量。
函数属性:
length属性:即函数的形参个数(函数调用时期望传入的实参个数):arguments.callee.length.
prototype属性:每个函数都包含一个prototype属性,这个属性指向一个对象的引用,这个对象称作原型对象,新创建的对象会从原型对象
上继承属性。
函数方法:
call方法:第一个参数是要调用的函数的母对象,在函数体内通过this来获得对他的引用。第二个参数及后面的参数是就是要传入调用函数
的实参
apply方法:和call方法功能一样,区别:它传入的实参都放入一个数组中,如:f.apply(o,[1,2]);
bind()方法:将函数绑定至某个对象并传入一部分参数。在调用的时候可以传入另一部分参数。 如:function f(y){return
this.x+y;} var o ={x:1} var g=f.bind(o); g(2); 第一个参数即被调用函数的this指针,它可以为null。
toString()方法:大部分返回函数的完整源码。
Function()构造函数:用Function()构造函数来定义函数,如:var f=new Function("x","y","return x*y";); 与如下定义的函数等价:
var f=function(x,y){return x*y;}注:Function()构造函数除了最后一个参数代表函数体,其余都是函数的形参。都需要用“”括起来。函
数体代码的编译总是在全局作用域下执行。
高阶函数:接受一个或多个函数作为参数,并返回一个新函数,这个新函数可以带有参数。
不完全函数:即把一次完整的函数调用拆成多次函数调用,每次传入的实参都是完整实参的一部分,每个拆分开的函数叫做不完全
函数,每次函数调用叫做不完全调用。每次调用都返回一个函数,知道得到最终的运行结果为止,f(1,2,3,4,5)的调用等价为f(1,2)(3,4)
(5,6),和每次调用相关的函数就是“不完全函数”。
6 类与模块:
类和模块:如果两个实例都从同一个原型对象上继承了属性,则说他们是同一个类的实例。
类和原型:可以通过创建一个工厂函数用于创建对象,这个工厂函数定义了所要创建对象的属性,可以在这个工厂函数的属性
上定义原型对象(键值对 方法名/函数体)然后通过工厂函数创建继承了原型对象的实例 (通过inherit(原型对象)方法)。
类和构造函数:通过同一个构造函数创建的所有对象都继承自一个相同的原型对象(构造函数名.prototype属性)。定义构造函数
就是定义类,构造函数首字母大写。
类的标识:当且仅当两个对象继承自同一个原型对象是,它们才属于同一个类的实例。
constructor属性:每个javascript函数都自动拥有一个prototype属性,这个属性是一个对象,这个对象包含唯一一个不可枚举
的属性constructor,constructor属性的值是一个原构造函数对象。每个对象都包含一个constructor属性,它指向创建这个对象的构造函
数。预定义的原型对象包含constructor属性,通过显示创建的prototype对象不具有constructor属性(必须通过自己手动添加
constructor:构造函数名)。
javascript中的java式类继承:javascript中的构造函数对象中定义的属性和方法是属于某个实例的(构造函数上定义的方法通
常不使用this引用,而只对传入的参数进行操作。),javascript中原型对象上定义的属性和方法被所有实例所继承(通过this引用构
造函数中定义的字段和方法)。javascript实例对象(通过new创建的对象)上定义的属性和方法是不会被所有实例共享的。
类的扩充:基于原型的继承机制是动态的,对象从原型继承属性,如果创建对象之后原型的属性发生变化,会影响到所有继承
这个原型的实例对象。可以通过给原型对象增加新方法来扩充javascript类。可以从所有的对象,如:数字原型Number,字符串原型
String,数组原型Array,函数原型Function对象原型Object增加方法。这样所有的同类对象的实例会自动继承对应的方法。
类和类型:无法用classof()函数,它只能返回javascript自定义的数据类型,所有的实例对象都返回“Object”。
instanceof运算符:如果o继承自c.prototype,则表达式o instanceof c返回true,非直接继承也能返回true。缺点:无法通过对象来
获取类名,只能检测对象是否属于指定的类名。
isPrototypeOf()方法:检测对象的原型链上是否存在某个特定的原型对象。与instanceof功能相同。原型对象.PrototypeOf(对
象);缺点:无法通过对象来获取类名,只能检测对象是否属于指定的类名。
constructor属性:可以直接获取对象所继承类的类名。以上3个方法在不同的框架中就无法识别。在多个执行上下文的函数检
测的结果也不相等。但它们的名称是一样的。
模块:javascript中没有定义用以支持模块的语言结构,很多框架都包含模块系统,如:node.js的module.exports和require函
数,用以声明(导出,可以导出一个构造函数的实例,即一个new创建的对象。也可以导出一个构造函数(然后在加载该模块时再
new初始化对象)。)和加载模块(先加载模块,然后通过new通过命名空间来调用所需构造函数或直接使用已初始化的对象)。
7 正则表达式:
正则表达式的定义:
直接量,如:var pattern = /s$/;//包含在一对斜杠之间。用构造函数RegExp()定义:var pattern=new RegExp(“s$”);
直接量字符:所有的字母和数字都是按照字面含义进行匹配,
非字母的字符匹配:使用反斜杠作为前缀进行转义。
直接量字符及匹配如下:
字母与数字:自身,
\o:Null字符,
\t:制表符,
\n:换行符,
\v:垂直制表符,
\f:换页符,
\r:回车符,
\xnn:由十六进制数nn指定的拉丁字符,
\uxxxx:由十六进制数xxxx指定的unicode字符,
\cX:控制字符:^X,
许多标点符号具有特殊含义(^ $ . * + ? = ! : | / \ ( ) [ ] { }):必须使用反斜杠进行匹配,
其他标点符号没有特殊含义:可直接进行匹配。
字符类:匹配字符类中的其中的任何一个字符(只匹配一个):
[...]:放括号内的任意字符,
[^...]:不在放括号内的任意字符,
. :除换行符和其他unicode行终止符之外的任意字符,
\w :任何ASCII字符组成的单词等价于[a-zA-Z0-9] ,
\W:任何不是ASCII字符组成的单词等价于[^a-zA-Z0-9],
\s:任何unicode空白符(空格符,制表符,和其他的unicode空白符),
\S:任何非unicode空白符的字符,
\d任何ASCII数字等价于[0-9],
\D:除了ASCII数字之外的任何字符等价于[^0-9],[\b]:退格直接量。
重复:
{n,m}:匹配前一项至少n次但不超过m次,
{n,}:匹配前一项n次或者多次,
{n}:匹配前一项n次,
?:匹配前一项0次或者1次,
+:匹配前一项1次或多次,
*:匹配前一项0次或多次.
非贪婪的匹配:重复中使用的匹配都是贪婪匹配(匹配重复字符是尽可能多的匹配),非贪婪的匹配只须在匹配的字符后
跟随一个问号即可,如:"??","+?","*?"," {1,5}?",非贪婪匹配会寻找字符串中第一个可能匹配的位置,从这个位置匹配到最后。
指定选择项:
字符(|)用于分隔供选择的字符,选择项的尝试匹配次序是从左到右,直到发现了匹配项。如果左边的匹配项匹配,
就忽略右边的匹配项。
分组:一个用途:使用圆括号来作用,用于将处理整个括号组成的单元。“+”,"?"|"*"对单元进行处理。 另一个作用是在完整
的模式中定义子模式,当一个正则表达式成功与目标字符串匹配时,可以从目标串中抽出与圆括号中的子模式相匹配的部分。 还有
一个作用:在同一正则表达式后部引用前面的子表达式相匹配的文本的模式的引用,通过在字符"\"后加一位或多位数字来实现。这
个数字指定了正则表达式中括号的位置(参与计数的是左括号的位置)。
仅分组不提供引用: (?: )只提供分组功能,不能对其进行 \数字 进行引用。
指定匹配位置:只用于指定匹配的位置,不匹配某个可见的字符,指定匹配发生的合法位置。 如:^用来匹配字符串的开
始,多行检索中,匹配一行的开头,$用来匹配字符串的结束,多行检索中,匹配一行的开头。\b匹配一个单词的边界,即位于\w和
\W之间的边界,或位于\w和字符串的开头或者结尾之间的位置。\B匹配非单词边界的位置。
(?=p)要求接下来的字符都与p匹配,但不能包括p的那些字符。 (?!p)要求接下来的字符不与p匹配。
修饰符:它们不是位于\ \之间的,而是位于第二条\之后的,支持三个修饰符:
g:匹配是全局的,找出被检索字符串中的所有匹配,而不是找到第一个之后就停止。
i:说明模式匹配是不区分大小写的。
m:用于在多行模式中执行匹配,^ $除了匹配字符串的开始和结尾,还匹配每行的开始和结束。
执行正则表达式模式匹配和检索替换操作的方法:
String中使用正则表达式的方法:
search():第一个参数是一个正则表达式,返回第一个与之匹配的字串的起始位置。如果找不到则返回-1。如果参
数不是正则表达式,通过RegExp()构造函数转换为正则表达式。不支持全局索引。
replace():用于执行检索与替换操作,第一个参数是一个正则表达式, 第二参数要进行替换的字符串,如果第一
个参数是字符串而不是正则表达式,则直接搜索这个字符串。第二个参数可以是一个函数,动态得计算替换字符串,也可以是$数
字,引用数字所代表括号的分组。
match():唯一参数是一个正则表达式,返回由匹配结果组成的数组。没有设置修饰符g,就不会进行全局索引,只
索引第一个匹配,第一个元素是匹配到的完整的匹配,第二个元素是第一个括号括起来的表达式匹配的字串。
split():将调用它的 字符串或一个正则表达式参数 拆分成 一个字符串组成一个数组,使用的分隔符是split()的参数。
RegExp对象:
RegExp()构造函数:第一个参数是正则表达式的主体部分,就是/ /之间的部分,传入字符串表述的正则表达式时,必须
将\替换成\\. 第二个参数是可选的,修饰符的组合。 在动态创建正则表达式时构造函数非常有用。
属性:包含5个属性:
1属性source:只读的字符串,包含正则表达式的文本。
2属性global只读的布尔值,说明这个正则表达式是否带有修饰符g。
3属性ignoreCase是一个只读的布尔值,说明正则表达式是否带有修饰符i。
4属性multiline是一个只读的布尔值,是否带有修饰符m。
5属性lastIndex是一个可读写的整数,如果匹配模式带有g修饰符,这个属性存储在整个字符串中下一次检索的开
始,每当在字符串找到最后一个匹配项后,在使用这个RegExp对象开始新的字符串查找之前,都应当将该属性设置为0.
方法:
exec()方法:参数是一个字符串,和match()方法类似,没有找到匹配返回null,找到匹配,结果与match()一样,属
性index包含发生匹配字符的位置,属性input引用的是正在检索的字符串。和match()方法不同,不管是否具有全局属性g,返回的结
果的相同。 当具有g修饰符:把当前正则表达式对象的lastIndex属性设置为紧挨着匹配的字符串的首字符位置(第二个匹配完整正则
表达式的字符串,非括号表示的子串),当第二次调用exec()时,将从将从lastIndex属性所示的字符开始检索,没有匹配结果将
lastIndex设置为0。
test()方法:参数是一个字符串,如果包含正则表达式的一个匹配结果,则返回true。
8 注意点和具体问题详解:
1.js中的作用域是通过作用域链来实现的, 这个链, 是由一个一个的活动对象组成的, 最顶级的活动对象是window
2. 在js中, 在每一个执行点, this关键字都指当前函数(方法)的所有者.
3. 每个属性,其实都会定义成当前活动对象的属性, 在顶级文件中的每个函数定义,变量定义, 都定义成window对象的属性.
4. 对于函数, 如果通过函数表达式定义的函数, 则在函数表达式执行前, 该函数不可用. 而如果是通过函数定义式定义的函数, js会把它
的定义提前, 也就是说在函数定义式之前, 该函数都可用.
5. 因为活动对象链的特性, 所以js支持闭包.当一个函数嵌套另一个函数,
函数对象有可以访问的prototype属性, 一般对象不是没有prototype属性, 只是没有可以访问的prototype属性.(严格来讲, 一般对象只有
只能JS引擎内部访问的”[[prototype]]”属性
语句和表达式的区别:
JavaScript中的表达式和语句是有区别的.一个表达式会产生一个值,它可以放在任何需要一个值的地方,比如,作为一个函数调用的参数.
下面的每行代码都是一个表达式:
myvar
3 + xmyfunc("a", "b")
语句可以理解成一个行为.循环语句和if语句就是典型的语句.一个程序是由一系列语句组成的.JavaScript中某些需要语句的地方,你可
以使用一个表达式来代替.这样的语句称之为
表达式语句.但反过来不可以:你不能在一个需要表达式的地方放一个语句.比如,一个if语句不能作为一个函数的参数.
var a=10; 与 a=10的区别:
当在过程级中声明一个变量时,它不能用于全局范围;这种情况下,变量声明必须用var关键字。
⒈在一个过程级中(即位于function的定义范围内,无论是函数,还是类)的任何地方,包括在一个区块里(for,while,if……),定义变量时,使用var定义,则此变量只在这个
过程级内起作用,反之(不使用var定义,或在过程级外var定义的变量)为全局变量。
⒉在过程级外定义变量时,无论是否忽略var,都将定义一个全局变量。变量的边界:
JS和其他语言有不一样的地方,变量的范围不以“{}”作为边界,而是以"function(){}"为边界,而且在过程内可以很轻松的定义全局变
量。如果不注意这个问题的话,是很容易产生不可预知的错误的。
对于使用var,我的建议是要养成好的使用习惯:
⒈在程序的开头,统一定义全局变量;
⒉所有的变量在定义时都要加上var;
⒊尽量不要在不同的过程中使用相同的变量名。