JS高级程序设置笔记(二)
5.4 RegExp类型
用这个类来表示正则表达式。
var expression = /pattern/flags;
pattern部分是任何简单的或者复杂的正则;每一个正则都有一个或者多个标志。
正则表达式匹配模式下支持下列3个标示
1:g 全局模式
2:i 不区分大小写
3:m 表示多行
5.4.1RegExp实例属性:
1:global:布尔值,表示是否设置了g标志。
2:ignoreCase:布尔值:表示是否设置了i标志
3:lastIndex:整数,表示开始搜索下一个匹配的字符位置,从0算起。
4:multiline 布尔值:表示是否设置了m标志
5:source:正则表达式的字符串表示。
5.4.1RegExp实例方法
该对象的主要方法是exec(),用来补货组 接收一个参数。返回的数组虽然是Array的实例,单包含了两个额外的属性index(位置) 和 input(正则表达式)
function num(){5.4.3 RegExp构造函数属性
var text = "mom and dad and baby";
var pattern=/mom( and dad (and baby)?)?/gi;
var matches = pattern.exec(text);
document.write(matches.index);
document.write(matches.input);
document.write(matches[0]);
document.write(matches[1]);
document.write(matches[2]);
}
num();
RegExp构造函数:
长属性名 短属性名 说明
input $_ 最近一次要匹配的字符串。
lastMatch $& 最近一次的匹配项。
LastParent $+ 最近一次匹配的捕获组
LeftContext $` input字符串中lastMatch之前的文本
multiline $* 布尔值,表示是否所有表达式都使用多行模式。
rightContext $' input字符串中lastMatch之后的文本
RegExp构造函数的各个属性返回了下列的值
input:属性返回了原始字符串
leftContext:返回了单词short之前的字符串,而rightContext返回了之后的字符串
lastMatch:属性返回最近一次与整个正则表达式匹配的字符串
LastParent:属性返回最近一次匹配的捕获组
5.4.4 模式的局限性
下面列出了正则不支持的特性
匹配字符串开始和结尾的/A和/Z锚 支持插入符号(^)和美元符号($) |
向后查找(lookbehind)支持向前查找lookahead
|
并集合交集类
|
原子组
|
unicode支持(单个字符除外)
|
命名的捕获组(但是支持标号的捕获组)
|
s(single,单行)和X (free-spacing,无间隔)匹配模式
|
条件匹配
|
使用正则表达式注释
|
|
5.5 function类型
每个函数都是function类型的实例
function sum(num1,num2){
return num1+num2;
};
var sun=function(num1,num2){
return num1+num2;
}
5.5.1没有重载(深入理解)
在JS中是没有方法的重载的,如果有两个相同命名的函数,后面的函数会覆盖前面的函数
5.5.3 作为值的函数
函数本身就是一个变量,所以函数也可以用值来使用,可以将一个函数作为另一个函数的返回结果
function callSomeFunction(someFunction,someArgument){5.5.4函数的内部属性
return someFunction(someArgument);
}
function add10(num){
return num+10;
}
var result = callSomeFunction(add10,10);
alert(result);
在函数内部有两个特殊的属性:arguments(包含参数的数组)和this()
arguments是一个类数组对象,包含着传入函数中的所有参数。这个对象还有一个特殊的属性叫做callee的属性
该属性是一个指针,拥有指向这个对象的函数:
例子:求一个数的阶乘
//阶乘 递归函数耦合性太强,消除耦合性
function factorial(num){
if(num>=1){
return 1;
}else{
return num*factorial(num-1);
}
};
function factorial(num){使用了arguments.callee方法:
if (num >= 1) {
return 1;
} else {
return num * arguments.callee(num-1);
}
};
</script>
callee是arguments的一个属性成员,他表示函数的对象本身的引用,这有利于匿名。
函数体内的另一个对象是this.this指的就是环境对象,this就是对象Window
例子:
window.color="red";
var o = {color:"blue"};
function sayColor(){
alert(this.color)//输出的是window的颜色
}
ECMAScript5规范了另一个函数对象的属性:caller
用来返回调用者
5.5.5函数属性和方法
length:表示函数希望接收的命名参数的个数
每个函数都包含两个非继承而来的方法:apply()和call()用来设置函数体this内的值。
call():调用一个对象的一个方法,以另一个对象替换当前对象,说明:call方法可以用来代替另一个方法。
apply()接收两个参数,一个是在其中运行的作用域,另一个是参数数组。
call()与apply()的作用相同,他们的仅是在接参数不同。第一个是this,剩下的全部传递给函数。
ECMAScript5 定义了一个新的方法:bind():这个方法会创建一个函数的实例,其this值会被绑定到传给bind()函数的值。例如:
window.color="red";
var o ={color:"blue"}
function sayColor(){
alert(this.color);
}
var objectSayColor = sayColor.bind(o);
objectSayColor();//blue;
5.6基本包装类型
为了便于操作基本类型值 ECMAScript提供了3个特殊的引用类型:boolean,Number和String
访问过程出于一种读取模式,也就是要存内存中读取这个字符串的值。味杂读取模式中访问字符串时,后台都会完成下列处理(1)创建String类型的一个实例
(2)在实例上调用指定的方法:
(3)销毁这个实例
5.6.1Boolean类型
建议永远不要使用boolean对象
5.6.3 String类型
定义String对象的语法
var StringObject = new String("hello world");
alert(StringObject.length);//"11"
1:字符方法:
两个用于访问字符串中特定的方法是:chatAt(),chartCodeAt();
一个用于返回查找位置的字符,另一个返回该字符的字符编码。
var string ="hello";
string.charAt(1)//e
string.chartCodeAt(1);//101e的字符编码
2:字符串操作方法
concat()方法,用于将一或多个字符串拼接起来,返回拼接得到的新字符串。
var string="hello";
string.concat("world");
alert(string);//hello world
ECMAScript还提供了三个基于字符串创新的方法:slice()、sbuString()、sbustr();
接受两个参数,一个是起始位置,另一个是结束位置。
就是对原有字符串进行截取,并形成一个新的字符串,不会对原有的字符串进行改变
3:字符串位置方法:indexof(),lastIndexOf()
前一个方法是返回搜索的值在原有字符串中的位置,如果有多个同样的搜索值,他只会返回第一个值得位置;
后一个方法顾名思义就是返回搜索值在原有字符串中最后一次出现的位置。
接收两个参数,第一个是要搜索的值,第二个是起始位置
4:trim()方法
ECMAScript5为所有字符串定义了trim()方法。
使用这个方法会删除原有字符串前置和后置所存在的字符串,然后产生一个类似副本的新字符串。
5:字符串大小写
有四个方法:
转换成大写:(1)toUpperCase()(2)toLocaleUpperCase()
转换成小写:(1)toLowerCase()(2)toLocaleLowerCase()
6:字符串的模式匹配方法:
match()只接受一个参数,要么是一个正则表达式,要么是一个RegExp
用来匹配正则里的值
search()返回字符串中第一个匹配的索引;如果没有找到匹配项,返回-1;
replace():接收两个值,第一个是索引的值,第二个是需要替换的值。
7:localeCompare()方法:
用于字符串之间的比较;
5.7单体内置对象:
已经存在了的对象,在程序之前,他们已经实例化过了,例如object,Array和String。
5.7.1global对象
全局对象所有在全局作用域中定义的属性和函数,都是Global对象的属性
isNaN,isFinite(),parseInt(),parseFloat()全是Global的方法
1:URI编码方式:通用资源标识符
encodeURI() encodeURIComponent()方法可以针对URI进行编码,以便发给浏览器
2:eval()方法
一个完整的ECMAScript的解析器
只接受一个参数及要执行的ECMAScript的字符串
3:global对象的属性
不能给undefined NaN和infinity赋值,
4:window对象
是BOM中所有对象的核心
5.7.2Math对象()数学方法
min()和max()方法,用于确定一组数值中的最大值和最小值的方法
例:
var min = Math.min(1,2,3);//1
var max = Math.Max(1,2,3);//3
3:舍入方法
Math.ceil()向上舍入,取大的25.1取26
Math.floor()向下舍入 取小的25.9取25
Math.round()执行标准舍入 四舍五入
4:random()
产生随机数
selectFrom(x,y)随机抽出X-Y中的一个值,总数是ifx>y x-y+1个
6:面向对象的程序设计
类和对象的区别,类是抽象的,对象是具体的,例如:手机是一个大类,苹果6手机就是一个对象,一个是很高层面的理解,另一个又是很基础的理解。对象是特定类的一个实例
属性是对象固有的:如:车有最大马力,重量等等,方法是对象能干什么,比如车能启动来开,大方形盘就能转向等等。
6.1理解对象
//创建一个对象用这段代码来理解对象、属性、方法:
var person={
name:"gavin",
age:"23",
job:"IT engineer"
}
person.sayHey=function(name){
alert("Hello"+name);
}
document.write(person.age+person.job+person.name);
person.sayHey("JJ");
这里的对象是一个person 它是object类的一个实例 他有三个属性、名字、年纪、工作、
他还有他一个方法,可以理解成这个对象能干什么,他可以说HELLO to "someone"这里的some需要你给它提供参数
6.1.1属性类型
1:数据类型:
数据属性包含一个数据值的位置。在这个位置上可以读取和写入值,数据属性有4个描述其行为的特性
[configurable]:表示能否通过delete删除属性从而重新定义属性
[Enumerable]:表示能否通过for-in循环返回属性
[Writable]:表示能否修改属性的值
[Value]:包含这个属性的数据值
要修改属性默认的属性,必须使用一个神奇的方法 object.defineProperty()
这个神奇的方法可以接受三个值:属性所在的对象,属性的名字和一个描述符的对象
Object.defineProperty(person,"name",{
writable:true,//这里如果填的是false 的话就不能通过.属性来冲新设置值了例:person.name="gavin"//不会修改属性
value:"zhihao"
});
person.name="gavin";
2:访问器属性
可以通过设置get 和set方法来获取或者设置对象的属性的值
Object.defineProperty(person,"age",{6.1.2定义多个属性
get :function(){
return this.age;
},
set:function(val){
this.age=val;
}
});
使用Object。defineProperties()方法
var book={};
Object.defineProperties(book,{
_year:{
value:2004
},
_edition:{
value:1
},
year:{
get:function(){
return this._year;
},
set:function(NewValue){
if(NewValue>2004){
this._year=NewValue;
this._edition+=NewValue-2004;
}
}
}
})
6.1.3读取属性的特征:
var d = Object.getOwnPropertyDescriptor(book,"_year");6.2创建对象
6.2.1工厂模式:
把一个对象封装起来,只留了一个接口,可以通过接口传入参数来更改对象的值。
6.2.2构造函数模式
function Person(name,age,job){用java的编程思想来理解这个:创建了一个Person类,而不是再使用Object类,他其实就相当于一个框架,this相当于当前的类,我们可以通过New 来创建一个Person类的对象
this.name=name;
this.age=age;
this.job=job;
this.sayHi=function(someOne){
alert(this.name+"say Hello to"+someOne);
}
}
1:当构造函数调用
function Person(name,age,job){2:当普通函数调用
this.name=name;
this.age=age;
this.job=job;
this.sayHi=function(someOne){
alert(this.name+"say Hello to"+someOne);
}
}
var person = new Person("gavin",23,"it");
document.write(person.age+" "+person.name+" "+person.job);
Person("a",2,"a");//添加到window
window.sayName();
6.2.3原型模式prototype(原型)属性。
这个属性是一个指针,指向一个对象,这个对象的用途是包含可以由特定类型的所有实例共享的属性和方法。
个人的理解方法:
你玩游戏有一个大号,有一个仓库,仓库里有很多钱、装备之类的,然后你又用这个账号创建了一个小号,这个小号就能使用这个仓库里的所有东西。
function Person(){这就是一个原型的构造函数。
Person.prototype.name="gavin";
Person.prototype.age=23;
Person.prototype.job="software engineer";
Person.prototype.sayName=function(){
aler(this.name);
}
}
我们可以以这个原型类创建对象,当我们为自己创建的对象付新值得时候,原型构造函数里的函数值并没有被改变,只是被屏蔽了。换句话说就是,新建的对象中的属性会阻碍我们看到原型中的属性。当我们使用delete操作符删除了我们自己定义的属性之后,原型中的属性又可以重新正常显示了,
我们可以用hasOwnProperty()方法来检测值是来自于原型还是来自于自定义,原型的话返回值是false,自定义的话返回值是true。
2:原型与in操作符:
in操作符只要能通过对象能够访问到属性就返回true,hasOwnPeoperty()只在属性存在于实例中才返回ture,只要in返回true,hasOwnPeoperty()返回false就能确定属性是原型中的属性。
hasPrototypeProperty()接收两个参数,一个是对象,一个是属性,如果属性是原型中的就返回true,如果重写了属性的值,就返回false;
要取得对象上所有可枚举类的实例属性,可以使用ECMAScript5中的object.key()方法,这个方法接收一个对象作为参数,返回一个包含所有可枚举属性的字符串数组。
3:更简单的原型语法:
function Person(){}和上面的创建方法有一点不同的是constructor属性不在指向这个Person了。
Person.prototype={
name:"gavin",
age:23,
job:"software engineer",
sayName:function(){
alert(this.name);
}
}
如果constructor值真的很重要,我们可以加上他
constructor:Person,
4:原型的动态性
当我们先创建一个对象再重新写了原型类之后,对象的调用就会出现问题。
6.2.4
组合使用构造函数模式和原型模式:
把自己特有的东西写进构造函数里,把公用的方法提出来用原型的方法去写
function Person(name,age,job){}
this.name=name;
this.age=age;
this.job=job;
Person.Prototype={
constructor:person,
sayName:function(){
alert(this.name);
}
}
所有属性都是再构造函数中完成的,方法都是再原型中完成
6.2.5动态原型模式
把所有信息都封装在了构造函数中,而通过构造函数中初始化原型,保持了同时使用构造函数和原型的优点。可以通过检查某个应该存在的方法是否有效。来决定是否要初始化原型。
6.2.6寄生构造函数模式
基本思想,创建一个函数,该函数的作用仅仅是封装创建对象的代码,然后再返回新的创建对象;但是从表面上来看,就和构造函数是差不多的。在构造函数内部又创建了一个object类的对象,对这个对象进行操作,然后返回这个函数
6.2.7稳妥构造函数模式
稳妥对象这个概念。所谓稳妥对象,指的是没有公公属性,而且方法也不引用this的对象。稳妥对象最适合在一些安全的环境中。
6.3:继承
继承的两种方式,接口继承和实现继承。接口继承只继承方法签名,而实际继承则继承继承实际的方法。
6.3.1原型链
基本思想是利用原型让一个引用类继承另一个引用类的属性和方法。
6.3.2借用构造函数
基本思想,在子类型构造函数的内部调用超类型构造函数。
函数只不过是在特定环境中执行代码的对象,因此通过使用apply()和call()方法可以在新创建的对象上执行构造函数。
6.3.3组合继承
使用原型链实现对原型属性和方法复用,又能够保证每个实例都有它自己的属性。、
6.3.4原型式继承
思想是借助原型可以基于已有的对象创建新对象,同时还不用因此创建自定义类型
形象的说就是站在巨人的肩膀上摘苹果,前提是必须有一个巨人。
var Person = {会丰富模板
name: "gavin",
friends: ["a", "b", "c"]
};
var onePerson = Object(Person);
onePerson.name = "zzh";
onePerson.friends.push("d");
var otherPerson = Object(onePerson);
otherPerson.name = "zzh";
otherPerson.friends.push("E");
alert(Person.friends);
7函数表达式:
定义函数的方式有两种:一种是函数声明,另一种是函数表达式。
函数声明的语法:
function functionName(arg0,....){
//函数体
}
函数声明提升:就是在执行代码之前就会先读取函数
sayHi();
function sayHi(){
alert("Hi!");
}
第二种创建函数的方式是使用函数表达式。函数表达式有几种不同的语法形式,最常见是:
var functionName=function(arg1....){
//函数体
}
匿名函数:创建一个函数并赋值给一个变量,因为function关键字后面没有标识符
函数表达式和其他表达式不一样,一定要先声明后引用
函数声明和函数表达式的区别:函数声明可以先引用后声明,而函数表达式一定要先声明后引用
7.1递归
递归函数是一个函数通过调用自己名字的情况下产生的
一个经典的递归函数
function factorial(num){
if(num<1){
return 1;
}else{
return num*factorial(num-1);
}
}
arguments.callee 指向一个正在执行的函数指针,因此他可以用来实现函数的调用
在严格模式下不能使用这个函数,会导致错误,可以用命名函数来达成相同的结果
var factorial=(function f(num){
if(num<1){
return 1;
}else{
return num*f(num-1);
})
7.2 闭包
首先基本上所有的编程语言都有类似的特性,局部方法可以访问外部父类方法的属性,也就是说,子类或子方法可以访问父类的资源。
就是在一个函数内创建一个子函数,这个子函数是用来得到他父元素的属性值得,设置一个返回值就是父元素的属性,然后外部调用这个函数的内部函数,就能访问到这个函数的属性值了,这个函数的子函数就称为闭包
function func3(){
var num3 = 44;
function func4(){
return num3;
}
return func4;
}
var func = func3();
console.log(func());
{
在外部无法获取到func3内部的局部变量,但是func3内部的局部方法func4却可以获取到,因此 返回一个func4的引用 ,这样在外部通过这个func4就可以获取到func3的内部变量。
虽然是绕了一个圈子,但是在方法外部却通过这样一个手段获取到了内部的值。
而这个方法内的局部方法func4就叫做闭包,按照很多书上的概念,这个方法搭建了方法内部与方法外部的桥梁,使得在外部也可以任意的获取到方法内部的资源。
但是闭包会造成变量在内存中持久占用,因此会有一定的性能问题,最好不要轻易使用,即便使用也要在恰当的实际进行释放。
}
作用域链的本质是一个指向变量对象的指针列表,它只引用但不实际包含变量对象。
What is right to be done cannot be done too soon