JavaScript学习笔记(二)

引用类型


(1)Object类型

创建对象:

//方法1
person = new Object();
person.name="Alen";
person.age=21;

//方法二
person = {
    name : "Alen",
    age : 21;
};

//方法三
person={};
person.name="Alen";
person.age=21;

访问对象属性:

//点表示法
alert(person.name);
//下标索引法
alert(person["name"]);
下标索引法的优点在于可以用字符串变量来访问属性,如:

var prop = "name";
alert(person[prop]);

(2)Array类型
创建数组:

var colors = new Array();
var colors = Array();

var colors = new Array(3); //定义长度为3
var colors = Array(3);
var colors = new Array("blue"); //数组长度为1,有一个元素

var colors = ["red","blue","black"];
var colors = [];
colors[3]="black"; //则数组长度为4,内容为3个undefined和最后一个black
数组的特点:引用类型,数组内各元素类型可以不一致,数组动态增长(访问越界下标可插入),未赋值数组元素为undefined。


数组方法:

//字符串转换
var colors = ["red","blue"];
alert(colors);  //隐式调用toString或者ValueOf转换为字符串"red,blue"
alert(colors.join("||")); //分割符由","变成"||",即转换字符串为"red||blue"

//栈方法
var colors = ["red","blue"];
var newlen = colors.push("black"); //数组red,blue,black
var elem = colors.pop(); //数组red,blue,返回black

//队列方法
var elem = colors.shift();  //数组blue,返回red
var newlen = colors.unshift("red"); //数组red,blue

//排序方法
var arr = [1,5,,0,15,10];
arr.reverse(); //[10,15,0,5,1]
arr.sort(); //先转成字符串,再按字符串升序排序,[0,1,10,15,5]
arr.sort(compare); //自定义比较函数,用>,<号比较,可以正确比出元素间的大小,正确排序

//操作方法:拼接新建
var colors = ["red","blue"];
var colors2 = colors.concat("red",["yellow","black"]); //colors不变,返回的colors2为red,blue,red,yellow,black
//操作方法:片段复制
var colors = ["red","blue","black","yellow"];
var colors2 = colors.slice(1); //colors2为:blue,black,yellow
var colors3 = colors.slice(1,3); //colors3为:blue,black
//操作方法:片段删除和插入
var colors = ["red","blue"];var removed = colors.splice(0,1); //colors中删除了第0项,并返回第0项给removed
var removed = colors.splice(0,0,"red","yellow"); //结果为red,yellow,blue。即删除0个,并在第0位插入red和yellow,removed为空[]
 

 
  

(3)Date类型:

var now = Date(); //获取当前时间
var d = new Date(2012, 10, 1);  //2012年10月1日
var d = new Date('Oct 1, 2012'); //2012年10月1日

 另有各种获取年份,月份,时间,设置年月日的方法等等,各种格式。各种时区。 
  

(4)RegExp类型:正则表达式

var pattern1 = /at/g; //匹配所有at
var pattern2 = /[bc]at/i; //匹配第一个bat或cat,不分大小写
var pattern3 = /.at/gi; //匹配所有的以at结尾的3字符组合,不分大小写
形如:var pat = /pattern/flags;

这里的flag有三种:g(全局),i(大小写不敏感),m(多行模式)

这里的正则表达式为基础+拓展+Perl:有( [ { \ ^ $ | ) ? * + . ] }这些特殊含义的符号,还有\d,\s,[:digit:]等。

//查看属性
var pat = /[bc]at/i;
alert(pat.global); //false
alert(pat.ignoreCase); //true
alert(pat.multiline); //false
alert(pat.source); //"[bc]at"
alert(pat.LastIndex); //0,下次匹配时从哪个位置开始

//RegExp执行方法
var text = "mom and dad and baby";
var pat = /mom( and dad( and baby)?)?/i; //括号()内的内容视为?的一个单位,并且匹配()内的内容将会被捕获
var matches = pat.exec(text);
alert(matches.input); //输入的文本:mom and dad and baby
alert(matches.index); //本次匹配结果的起始位置 0
alert(matches[0]); //matches[0]总存放当前这次匹配匹配出的结果,mom and dad and baby
alert(matches[1]); //若有捕获,则将捕获结果放在matches[1],matches[2]...中,这里为第一个捕获结果" and dad and baby"
alert(matches[2]); //捕获" and baby"

/*当全局匹配时,可以多次执行,将依次获得所有的匹配结果。当非全局匹配时,永远是那个结果*/
var text = "cat, bat, pat";
var pat =/(.)at/gi;
matches = pat.exec(text);
alert(matches.index); //0
alert(matches[0]); //cat
alert(pat.LastIndex); //3

matches = pat.exec(text);
alert(matches.index); //5
alert(matches[0]);  //bat
alert(pat.LastIndex);  //8

//RegExp测试方法
if(pat.test(text)) {
alert("pattern match!");
} 
 
  
 
  
 
  

RegExp构造函数属性:

RegExp中包含一些静态的,作用域中所有pattern共有的一些属性(在C++中理解为static属性),这些属性随着最近一次正则表达式的操作而变化,有:Input($_),lastMatch($&),lastParen($+),leftContext($`),rightContext($*),multiline($')。可以通过形如RegExp.Input和RegExp["$_"]来访问。另有RegExp.$1,RegExp.$1,……表示捕获组。其他具体含义查书吧。

(5)Function类型:

JS中的Function本质上是一个Object对象,由此定义函数的方法有:

function sum(num1,num2) {
    return num1+num2;
}

var sum = function(num1,num2) {
    return num1+num2;
};
/*但是声明式的写法,会在所有代码执行前先解析,表达式的写法只能在运行到时才解析。所以可以先调用函数后声明,但不能先调用函数后写函数对象定义表达式*/
函数名本质上是一个对函数对象的引用,由此可以更改函数名引用的函数:

function sum(num1,num2) {
    return num1+num2;
}
//更改为乘法函数
sum = function(num1,num2) {
    return num1*num2;
};
var res = sum(10,10); //结果为100
//更改为null
sum = null; //obj=null都是解除引用
由此可以理解为什么没有函数重载,因为函数名被覆盖了,可以解释为什么函数定义中还能定义函数了。其他:

/*函数作为值传递*/
function callSomeFunc(someFunc,someArg) {
    return someFunc(someArg);
}

function createCmpFcn(propertyName) {
    return function(obj1,obj2) {
        var value1 = obj1[propertyName];
        var value1 = obj1[propertyName];
        if(value1
 
  
 
  
 
  

 
  

这里的灵活,松耦合的感觉,有点像php中的$_post[$prop_name],$$var_name,C++中的map[prop_name],还有JS的obj[propName]。

函数内部对象:

有两个,arguments数组对象和this对象(可以理解为C++中的this指针,在这里指该函数执行时所处的作用域)。arguments这个Array对象中还包含一个callee属性,它反指向这个函数对象。这两者都有很多奇技淫巧。

function factorial(num) {
    if(num==1) return 1;
    return factorial(num-1)*num;
}
/*用arguments.callee实现松耦合*/
function factorial(num) {
    if(num==1) return 1;
    return arguments.callee(num-1)*num;
}

/*使用this*/
function showColor() {
    alert(this.color);
}
window.color="red";
o = {color:"blue"};
o.sayColor = sayColor;
sayColor(); //red,这里默认属于window作用域,因此this为window
o.sayColor(); //blue,这里this为o

 
  函数的属性和方法函数对象有两种属性,length和prototype。length表示函数希望接受的参数个数(即定义的参数列表长度),prototype属性中则包含了所有函数对象的方法(不止函数对象,多有对象都有这个属性来包含方法),包括有toString,ValueOf,call和apply。 
  call和apply是指将本函数放到某个作用域下执行(本质是改变函数this的值)

/*使用方法apply(this,[arg1,arg2,...])*/
//第一个参数传入要设置的作用域
//第二个参数传入参数数组
function showColor() {
    return this.color;
}
showColor.call(window); //red
showColor.call(o); //blue
/*这样比先把方法加入对象中,再调用省略了一步*/
用apply或call来扩充作用域的最大好处是对象不需要与方法有任何耦合关系。关于耦合不耦合,什么时候怎么设计比较好,这里理解总结得不够好,毕竟思维还停留在C++那里,需要多用多思考。


基本包装类型

在访问基本类型Boolean,String,Number时,会首先给创建一个相应的引用实例对象,访问之后,立即销毁这个实例。为什么要用一个实例对象把基本类型值包起来?因为在运行表达式的过程中,总是会需要用到tostring,ValueOf这些函数,因此包装上Object以后,能调用通用的这些方法。

每个包装对象的声明期只有一个语句长!不像普通的引用类型生命期为一个作用域。

var s1 = "some text";  //创建基本类型值和包装对象,然后销毁包装对象
s1.color = "red";  //又创建了一个包装对象,语句结束时又销毁了,因此color设置无效
alert(s1.color);  //undefined

可以显式地声明基本包装类型对象,它会像普通引用类型对象一样有作用域级的生命周期。

(1)Boolean类型

不建议使用!所有对象的布尔值为true。所以:

var bool_obj = Boolean(false);
var bool_value = false;
alert(typeof bool_obj); //Object
alert(typeof bool_vaue); //Boolean

var res = bool_obj && true;
alert(res);  //true
var res = bool_value && true;
alert(res);  /false
另外,Boolean包装对象有toString和ValueOf方法,它重写的Boolean版本。


(2)Number类型

/*toString方法*/
var num_obj = Number(10);
alert(num_obj.toString()); //10
alert(num_obj.toString(2)); //2进制"1010"
alert(num_obj.toString(16)); //16进制"a"

/*toFixed方法*/
alert(num_obj.toFixed(2)); //小数点后两位"10.00"
alert(typeof num_obj); //Object
另有toExponential(科学计数法)和toPrecision(精度)方法。

(3)String类型

//length属性
//访问字符
stringValue = "hello world";
stringValue.charAt(1); //'e'
stringValue.charCodeAt(1); //"101"
stringValue[1]; //'e',IE不支持

/*拼接新建concat*/
var str = "hello";
var res = str.concat("world");
alert(str); //hello
alert(res); //hello world

/*子串*/
/*substr,slice,substring都是子串函数,其中substr第二个参数为长度,substring和slice第二个参数为终点的后一位*/
var str = "hello world";
str.slice(3); //lo world
str.substring(3); //lo world
str.substr(3); //lo world
str.slice(3,7); //lo w
str.substring(3,7); //lo w
str.substr(3,7); //lo worl

/*子串查找*/
var str = "hello world";
str.indexOf("o");  //从前往后找一个匹配的,位置为4
str.lastIndexOf("o");  //从后往前找第一个匹配的,位置为7
str.indexOf("o",6);  //从6开始往后找第一个匹配的,位置为7
str.lastIndexOf("o",6);  //从6开始往前找第一个匹配的,位置为4

/*大小写转换*/
//略

/*模式匹配1*/
matches = str.match(pattern); //和pattern的后续处理一样
/*模式匹配2*/
var pos = str.search(pattern); //找出第一个匹配的位置,无匹配则为-1
/*模式匹配3*/
var res = str.replace("o","e"); //helle world
var res = str.replace(/o/g,"e"); //helle werld
/*replace详细用法请查书,replace第二个参数可以是函数对象,可以是字符串(包含$n捕获组等等特殊含义值)*/
/*模式匹配4*/
var colors = "red,blue,yellow,black";
var res = colors.split(","); //数组["red" , "blue" , "yellow" , "black"]
var res = colors.split(/[^\,]+/); //数组["," , "," , "," , ","]
 
  
 
  
 
  
 
  

 
  
内置对象

(1)Global对象

所有全局的属性方法最终都是全局对象的属性方法,所谓全局变量全局函数,即全局对象的属性方法。如:isNaN(),parseInt()等这些其实都是Global对象的方法。另外,Global对象还有encodeURI()方法,用于编码URI,eval()方法,用于执行写在字符串中的JS语句。Global对象无法直接访问,但是它是window对象的一部分,可以用window来显式访问这些全局变量和函数。


(2)Math对象

包括一些数学函数max,min,ceil,round,floor,sin,cos,abs,exp,random等等,等等。

要这样用:var max = Math.max(3,4,12,0); //12

你可能感兴趣的:(JavaScript)