资讯专栏INFORMATION COLUMN

JavaScript学习笔记 - 引用类型

dendoink / 958人阅读

摘要:构造函数本身就是一个函数,只不过该函数是出于创建新对象的目的而定义的。使用的构造函数是,它只为新对象定义了默认的属性和方法。第一种就是操作符后跟构造函数第二种是使用对象字面量表示法。

本文记录了我在学习前端上的笔记,方便以后的复习和巩固。

Object类型

Array类型

Date类型

RegExp类型

Function类型

基本包装类型

单体内置对象

引用类型的值(对象)是引用类型的一个实例。引用类型是一种数据结构,用于将数据和功能组织在一起。也常被称为类。引用类型有时候也被称为对象定义,因为它们描述的是一类对象所具有的属性和方法。

新对象是使用new操作符后跟一个构造函数来创建的。构造函数本身就是一个函数,只不过该函数是出于创建新对象的目的而定义的。

var person = new Object();

这段代码创建了Object引用类型的一个新实例,然后把该实例保存在变量person中。使用的构造函数是Object,它只为新对象定义了默认的属性和方法。

5.1 Object 类型

创建Object实例的方式有两种。
第一种就是new操作符后跟Object构造函数

var person = new Object();
person.name = "Nicholas";
person.age = 29;

第二种是使用对象字面量表示法。(简化创建包含大量属性的对象过程)

var person = {
    name : "Nicholas",
    age : 29
}

使用对象字面量语法时,属性也可以使用字符串

var person = {
    "name" : "Nicholas",
    "age" : 29,
    5 : true
}
//属性名会自动转换为字符串

另外,使用对象字面量语法时,如果留空花括号,则可以定义只包含默认属性的方法的对象

var person = {}; //与new Object()相同
person.name = "Nicholas";
person.age = 29;

在通过对象字面量定义对象时,实际上不会调用Object构造函数

对象字面量也是向函数传递大量可选参数的首选方式

function displayInfo(args) {
    var output = "";
    if(typeof args.name == "string"){
         output += args.name;
    }
    if(typeof args.age == "number"){
         output += args.age;
    }
    console.log(output)  //Nicholas29,Greg
}
displayInfo({
    name: "Nicholas",
    age: 29
});
displayInfo({
    name: "Greg"
});

这种传递参数的模式最适合需要向函数传入大量可选参数的情形。一般来讲,命名参数虽然容易处理,但是有多个可选参数的情况下就会显示不够灵活。最好的做法是对那些必须值使用命名参数,而使用对象字面量来封装多个可选参数。

一般访问对象属性都是点表示法。不过也可以使用方括号来访问对象的属性

console.log(person["name"]);    //"Nicholas"
console.log(person.name);    //"Nicholas"

//方括号语句主要优点是可以通过变量来访问属性
var propertyName = "name";
console.log(person[propertyName]); //"Nicholas"

通常,除非必须使用变量来访问属性吗,否则我们建议使用点表示法。

5.2 Array 类型

与其他语言不同,ECMAScript数组的每一项可以保存任何类型的数据,可以用数组第一个位置保存字符串,第二位置保存数值,第三位置保存对象,以此类推。而且ECMAScript数组的大小是可以动态调整的,即可以随着数据的添加自动增长以容纳新增数据。

创建数组的基本方式有两种。第一种是使用Array构造函数:

var color = new Array();
var colors = new Array(20);        //将创建length值为20的数组
var colors2 = new Array("red", "blue", "green");   //创建一个包含3个字符串的数组
var names = new Array("Greg");  //创建一个包含1项的数组;

第二种方式是使用数组字面量表示法:

var colors = ["red", "blue", "green"] //创建一个包含3个字符串的数组
var names = [];  //创建一个空数组
var values = [1,2,];  //不要这样!这样会创建一个包含2或3项的数组
var options = [,,,,,];  //不要这样!这样会创建一个包含5或5项的数组

与对象一样,在使用数组字面量表示法时,也不会调用Array构造函数(Firefox3及更早版本除外)

读取数组和数组length

var colors = ["red", "blue", "green"];
var names = [];    
colors[2] = "black";    //修改第三项
colors[3] = "brown";    //新增第四项
console.log(colors[0]);   //"red"
console.log(colors.length);  //4
console.log(names.length);  //0

//数组length不是只读的,通过设置这个属性可以从数组的末尾移除项或添加新项
colors.length = 2;        //修改数组的长度为2,数组就只有2个项了
console.log(colors[2]); //undefined
colors.length = 4;            
console.log(colors[3]);   //undefined;

利用length属性也可以方便的在数组末尾添加新项

var colors = ["red", "blue", "green"];
colors[colors.length] = "black";
colors[colors.length] = "brown";

colors[99] = "while";
console.log(colors.length)  //100
//位置5到98实际上都是不存在的访问他们都将返回undefined
5.2.1 检测数组

对于一个网页,或者一个全局作用域而言,使用instanceof操作符就能得到满意的结果:

if(value instanceof Array) {
    //...
}

instanceof操作符的问题在于,它假定只有一个全局执行环境。如果网页中包含多个框架,那实际上就存在两个以上不同的全局执行环境,从而存在两个以上不同版本的Array构造函数。如果你从一个框架向另一个框架传入一个数组,那么传入的数组与在第二个框架中原生创建的数组分别具有各自不同的构造函数。

为了解决这个问题,ECMAScript5新增了Array.isArray()方法。这个方面目的是最终确定某个值到底是不是数组,而不管它是在哪个全局执行环境中创建的。

if(Array.isArray(value)){
    //...
}

注意:不建议使用instanceof可能会出现异常,推荐使用Array.isArray方法

5.2.2 转换方法

所有对象都具有toLocaleString()toString()valueOf()方法。数组调用toString()方法会返回由数组中每个值得字符串形式拼接而成的一个以逗号分隔的字符串,调用valueOf()返回的还是数组。

var colors = ["red", "blue", "green"];
console.log(colors.toString());   //red,blue,green
console.log(colors.valueOf());    //返回整个数组
console.log(colors);               //返回整个数组
alert(colors.valueOf());          //red,blue,green
alert(colors);                      //red,blue,green

由于alert()要接收字符串参数,所以它会在后台调用toString()方法。

使用join()方法,则可以使用不同的分隔符来构建这个字符串。join()方法值接收一个参数,即用作分隔符的字符串,然后返回包含所有数组项的字符串。

var colors = ["red", "green", "blue"];
alert(colors.join(","));   //red,green,blue
alert(colors.join("||"));  //red||green||blue

如果数组中的某一项值是null或者undefined,那么该值在join()、toLocaleString()、toString()、valueOf()方法返回的结果中以空字符串表示。

5.2.3 桟方法 和 5.2.4队列方法 桟方法

在桟中项的插入(叫做推入)移除(叫做弹出),只发生在一个位置——桟的顶部。ECMAScript为数组专门提供了push()pop()方法,以便实现类似桟的行为。

push()方法可以接受任意数量的参数,把它们逐个添加到数组末尾,并返回修改后数组的长度。而pop()方法则从数组末尾移除最后一项,减少数组的length值,然后返回移除的项(值)。

队列方法

shift()方法能够移除数组中的第一个项并返回该项,同时将数组长度减1。结合使用shift()push()方法,可以使用队列一样使用数组

ECMAScript还为数组提供了一个unshift()方法。unshift()shift()的用途相反,它能在数组前端添加任意个项并返回数组的长度。因此同时使用unshift()pop()方法,可以从相反方向来模拟队列,即在数组前端添加项,从数组末端移除项。

//push
var colors = new Array();                    //创建一个数组
var count = colors.push("red", "green");    //推入两项(从后推入)
console.log(count);                            //2
count = colors.push("black");                //推入一项(从后推入)
console.log(count);                            //3
console.log(colors);                        //["red","green","black"]

//pop
var item = colors.pop();                    //取得最后一项
console.log(item);                          //"black"
console.log(colors.length);                 //2
console.log(colors);                        //["red","green"]

//shift
var shit = colors.shift();                    //取得第一项
console.log(shit);                          //"red"
console.log(colors.length);                 //1
console.log(colors);                        //["green"]

//unshift
var unshit = colors.unshift("red","blue");  //推入两项(从前推入)     
console.log(unshit);                           //3
console.log(colors);                        //["red","blue","green"]
5.2.5 重排序方法

reverse()sort()可以用来对数组进行重排序。
reverse()方法会反转数组项的顺序。

sort()方法会调用数组中每一项的toString()方法,并根据返回的字符串来对整个数组进行升序的排序,显然大部分情况下这种默认行为都不是我们所需要的。所以,我们可以传入一个比较函数作为sort()方法的参数,以便确定排序的顺序。

var num = [0, 5, 1, 10, 15];
num.sort();
alert(num);        //结果并非是0,1,5,10,15 而是0,1,10,15,5. 原因是sort比较的是字符串

/* 因此,sort()方法可以接收一个比较函数作为参数,以便我们指定哪个值位于哪个值的前面
** 比较函数接收两个参数,如果第一个参数应该位于第二个参数之前则返回一个负数,相等返回0,在之后就返回正数
*/
function compare(value1, value2){
    return value2 - value1; //降序则改为value1 - value2;
}

var num = [0, 5, 1, 10, 15];
num.sort(compare);
alert(num);//0,1,5,10,15
//若只是想反转数组,而不用排序就用reverse()
var num = [0, 5, 1, 10, 15];
num.reverse();
alert(num);//15,10,1,5,0
5.2.6 操作方法

concat():用于拼接数组

slice():用于获取数组中的某几个项

splice():主要用途是向数组的中部插入项

方法一:concat()方法可以基于当前数组中的所有项创建个新数组,简单点就是创建个副本,然后将接受到的参数添加到这个副本的末尾, 原来的数组不会动。

//可接收0个、1个或多个参数,没有参数就相当于复制当前数组,返回当前数组的副本
//参数若是值,就直接加到副本数组的末尾。参数若是数组,则将数组中的每一项加到副本末尾
var colors = ["red", "green", "blue"];
var colors2 = colors.concat("yello", ["black", "brown"]);

console.log(colors);        //red,green,blue原数组不动
console.log(colors2);        //red,green,blue,yello,black,brown

方法二:slice( )它能够基于当前数组中的一项或多个项创建一个新数组。接收一个参数或者两个参数,即返回项的起始位置和结束位置。不传则到末尾。如有2参,结束位置并不包括结束位置所在项(理解从0开始)。注意 不影响原数组

var arr = ["red", "green", "blue", "yello", ""purple];
var arr2 = arr.slice(1);        //因为第二个参数没有,所以从arr[1]开始获取后面全部项
var arr3 = arr.slice(1,4);        //截取arr[1]开始到arr[4]前
console.log(arr2);                //green,blue,yellow,purple
console.log(arr3);                //green,blue,yellow

方法三:在数组方法中算是最强大的方法了。它有很多种用法,主要用途是向数组的中部插入项,但使用这种方法的方式则有如下三种。

1.删除: 可以删除任意数量的项,只需指定2个参数: 要删除第一项的位置和要删除的项的数目。
举个栗子,splice(0,2); //删除数组的前两项

2.插入: 可以给指定位置插入任意数量的项。3+个参数,起始位置,0(要删除的项数为0项,也就是不删除)和要插入的项。如果要插入多个项,则把项作为第四、第五,以致任意多个项。
举个栗子: splice(2, 0, “red”, “yellow”, “green”); //在位置2依次插入red, yellow,green

3.替换 可以在指定位置删除任意多项,且同时删除任意多项。3个参数。 (startPos, delNum, insertNum) delNum 可以和insertNum不相等
`举个栗子: splice(2, 1, “red”, “green”);//删除位置2的1项,再从位置2插入red,green
注意: splice()方法始终返回一个从原始数组删除的项的数组,若没有删除项返回即为空。
简单点说,就是删了什么就返回了什么,没删就返回空。`

var arr = ["red", "green", "blue"];
var removed = arr.splice(0,1);            //删除第一项
console.log(arr);                        //green,blue
console.log(removed);                      //red,返回的数组中只包含一项

removed = arr.splice(1, 0, "yellow", "orange");        //从位置1开始插入两项
console.log(arr);                                    //green,yellow,orange,blue
console.log(removed);                                  //返回的事这个空数组

removed = arr.splice(1, 1, "red", "purole");        //插入两项,删除一项
console.log(arr);                                    //green,red,purole,orange,blue
console.log(removed);                                  //yellow,返回的数组中只包含一项
5.2.7 位置方法

indexOf():从数组的开头开始向后查找某一项

lastIndexOf():从数组的末尾开始向前查找某一项

两个方法都返回要查找的项在数组的索引位置,或者在没找到的情况下返回- 1

5.2.8 迭代方法

ECMAScript5为数组定义了5个迭代方法。每个方法都接收两个参数: 要在每一项上运行的函数和运行该函数的作用域对象(可选)—-影响this的值。每一项运行的函数包含三个参数: 数组项的值、该项在数组中的位置和数组对象本身。以下是五个方法的作用

every(): 对数组中每一项运行指定函数,如果该函数每一项都为true,则返回true,否则false。

filter(): 对数组中每一项运行指定函数, 返回该函数会返回true的项组成的数组(筛选出true的项)

forEach(): 对数组中每一项运行指定函数, 没有返回值。

map(): 对数组中每一项运行指定函数, 返回每次函数调用的结果组成的数组

some(): 对数组中每一项运行指定函数, 如果该函数对任一项返回true就返回true
以上方法都不会改变原数组的值。

方法的理解:

every() 可以理解成 &&,全为真则真

filter() 筛选,筛选出真的项组成的数组,

forEach() 可以遍历数组为数组的每个项添加方法

map() 映射 不管结果是什么,都返回一个由结果组成的数组,并不只是true false

some 可以理解 || 或操作,有一个为真则为真

5.2.9 归并方法

都接受两个参数:一个在每一项上都调用的函数和作为归并基础的初始值。传个reduce和reduceRight()的函数都接受4个参数:前一个值、当前值,项的索引和数组对象。

reduce(): 从数组第一项开始,逐个遍历到最后一项,可以用来数组求和

reduceRight(): 从数组最后一项开始,逐个遍历到第一项,可以用来数组求和

这两个方法都会迭代数组的所有项,然后构建一个最终返回的值。

//可以用来求和
var arr = [1,2,3,4,5];
var sum = arr.reduce(function(prev, cur, index, array){
    return prev + cur;
})
console.log(sum);   //15
5.5 Function类型

函数是Function类型的实例,函数是对象,因此函数名实际上也是一个指向函数对象的指针,不会与某个函数绑定。

//函数声明语法定义函数
function sum (num1, num2){
    return num1 + num2
};

//函数表达式定义函数
var sum = function sum (num1, num2){
    return num1 + num2
};

//使用Function构造函数
var sum = new Function("num1", "num2", "return num1 + num2");  //不推荐会导致解析两次代码

一个函数可能会有多个名字:

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

console.log(sum(10,10));  //20

var anotherSum = sum;        //此时,anotherSum和sum的指针都指向了同一个函数
console.log(anotherSum(10,10));  //20

sum = null                    //设为null指针就没了和函数断绝关系
console.log(anotherSum(10,10));  //20

注意:使用不带圆括号的函数名是访问函数指针,而非调用函数

5.5.1 没有重载(深入理解)

两个同名函数,后面的函数会覆盖前面的函数

5.5.2 函数声明与函数表达式
alert(sum(10,10));
function sum(num1, num2){
    return num1 + num2;
}

以上代码完全可以正常运行,因为在代码开始执行之前,解析器就已经通过一个名为函数声明提升的过程,读取并将函数声明添加到执行环境中。对代码求值时,JavaScript引擎在第一遍会声明函数并将它们放在源代码树的顶部。

alert(sum(10,10));
var sum = function sum(num1, num2){
    return num1 + num2;
}

这段会错误,原因是函数位于一个初始化语句中,而不是一个函数声明。

5.5.3 作为值得函数

因为ECMAScript中的函数名本身就是变量,所以函数也可以作为值来使用。也就是说,不仅可以像传递参数一样把一个函数传递给另一个函数,而且可以将一个函数作为另一个函数的结果返回。

function createComparisonFunction(proertyName) {
    return function(obj1, obj2) {
        var val1 = obj1[proertyName];
        var val2 = obj2[proertyName];
        if(val1 < val2){
            return -1;
        }else if(val1 > val2){
            return 1;
        }else{
            return 0;
        }
    }
}

var data = [{
    name: "Jason",
    age: 20
}, {
    name: "Cor",
    age: 30
}];

data.sort(createComparisonFunction("name");
console.log(data[0].name);                  //Cor
data.sort(createComparisonFunction("age"));
console.log(data[0].name);                  //Jason
5.5.4 函数的内部属性

在函数内部,有两个特殊的对象:argumentsthis

arguments的主要用途是保存函数参数但这个对象还有名叫callee的属性、该属性是一个指针,指向拥有这个arguments对象的函数。

function factorial(num) {
    if(num <= 1){
        return 1;
    }else{
        //return num * factorial(num-1)     //这个函数的执行与函数名factorial紧紧耦合在一起
        return num * arguments.callee(num-1);   //解除耦合
    }
};
var trueFactorial = factorial;
factorial = function(){
    return 0;
};
console.log(trueFactorial(5))   //120
console.log(factorial(5))         //0

函数内部的另一个特殊对象是thisthis引用的是函数执行的环境对象——或者也可以说this值(当在网页的全局作用域中调用函数时,this对象引用的就是window)

window.color = "red";
var o = { color : "blue" };

function sayColor() {
    console.log(this.color);
}

sayColor();      //"red"

o.sayColor = sayColor;        //把sayColor函数赋给对象o
o.sayColor();    //"blue"    //this的引用是对象o

ECMAScript5也规范化了另一个函数对象的属性:caller。这个属性中保存着调用当前函数的函数的引用,如果是在全局作用域中调用当前函数,它的值为null

function outer(){
    inner();
}

function inner(){
    console.log(arguments.callee.caller);    //为了实现更松散的耦合
}

outer();

注意:当函数在严格模式下运行是,访问arguments.callee会导致错误。ECMAScript 5 还定义了arguments.caller属性,但在严格模式下访问它也会导致错误,而在非严格模式下这个属性始终是undefined。定义arguments.callee属性是为了分清arguments.caller和函数的caller属性。以上变化都是为了加强这门语言的安全性,这样第三方代码就不能在相同的环境里窥视其他代码了。
严格模式还有一个限制:不能为函数的caller属性赋值,否则会导致错误。

5.5.5 函数属性和方法

ECMAScript的函数也是对象,因此函数也有属性和方法。每个函数包含两个属性: lengthprototypelength属性表示函数的参数数量

function jason(a, b, c) {};
console.log(jason.length); //3;

对于ECMAScript的引用类型而言,prototype是保存它们所有实例方法的真正所在。toString()valueOf()等方法实际上都保存在prototype名下,只不过是通过各自对象的实例访问。在创建自定义引用类型以及实现继承时,prototype属性的作用是极为重要的。在ECMAScript5中,prototype属性是不可枚举的,因此使用for-in无法发现。

每个函数都包含两个非继承而来的方法:apply() call()。这两个方法的用途都是在特定的作用域中调用函数,实际上等于设置函数体内this对象的值。首先,apply()方法接收两个参数:一个是在其中运行的作用域,另一个是参数数组。其中第二个参数可以使Array的实例,也可以是arguments对象。

1.apply():
/*定义一个人类*/
function Person(name,age)
{
    this.name=name;
    this.age=age;
}
/*定义一个学生类*/
function Student(name,age,grade)
{
    Person.apply(this,arguments);
    this.grade=grade;
}
//创建一个学生类
var student=new Student("qian",21,"一年级");
//测试
alert("name:"+student.name+"
"+"age:"+student.age+"
"+"grade:"+student.grade);
//大家可以看到测试结果name:qian  age:21  grade:一年级
//学生类里面我没有给name和age属性赋值啊,为什么又存在这两个属性的值呢,这个就是apply的神奇之处.

分析:
Person.apply(this,arguments);
this:在创建对象在这个时候代表的是student
arguments:是一个数组,也就是["qian”,”21”,”一年级”];
通俗的说:student去执行Person这个类里面的内容,在Person这个类里面存在this.name等之类的语句,这样就将属性创建到了student对象里面

2.call():

call()法与apply()方法作用相同,它们的区别仅在于接受参数的方式不同。在使用call()方法时,传递给函数的参数必须逐个列举出来

在上面Student函数里面可以将apply中修改成如下:

function Student(name,age,grade)
{
    Person.call(this,name,age);
    this.grade=grade;
}
//效果是一样的
3.什么情况下用apply,什么情况下用call

在给对象参数的情况下,如果参数的形式是数组的时候,比如apply示例里面传递了参数arguments,这个参数是数组类型,并且在调用Person的时候参数的列表是对应一致的(也就是Person和Student的参数列表前两位是一致的) 就可以采用 apply , 如果我的Person的参数列表是这样的(age,name),而Student的参数列表是(name,age,grade),这样就可以用call来实现了,也就是直接指定参数列表对应值的位置(Person.call(this,age,name,grade));

4.apply的一些其他巧妙用法

细心的人可能已经察觉到,在我调用apply方法的时候,第一个参数是对象(this), 第二个参数是一个数组集合, 在调用Person的时候,他需要的不是一个数组,但是为什么他给我一个数组我仍然可以将数组解析为一个一个的参数,这个就是apply的一个巧妙的用处,可以将一个数组默认的转换为一个参数列表([param1,param2,param3]) 转换为(param1,param2,param3) 这个如果让我们用程序来实现将数组的每一个项,来装换为参数的列表,可能都得费一会功夫,借助apply的这点特性,所以就有了以下高效率的方法:

Math.max 可以实现得到数组中最大的一项
因为Math.max 参数里面不支持Math.max([param1,param2]) 也就是数组

但是它支持Math.max(param1,param2,param3…),所以可以根据刚才apply的那个特点来解决 var max=Math.max.apply(null,array),这样轻易的可以得到一个数组中最大的一项(apply会将一个数组装换为一个参数接一个参数的传递给方法)
这块在调用的时候第一个参数给了一个null,这个是因为没有对象去调用这个方法,我只需要用这个方法帮我运算,得到返回的结果就行,.所以直接传递了一个null过去

var nums = [3, 2, 1, 5, 4];
var max = Math.max.apply(null, nums);
console.log(max);  //5

Math.min 可以实现得到数组中最小的一项

var nums = [3, 2, 1, 5, 4];
var min = Math.min.apply(null, nums);
console.log(min);  //1

Array.prototype.push 可以实现两个数组合并
同样push方法没有提供push一个数组,但是它提供了push(param1,param,…paramN) 所以同样也可以通过apply来装换一下这个数组,即:

var nums = [1, 2, 3, 4, 5];
var nums2 = [6, 7, 8, 9];
var max = Array.prototype.push.apply(nums, nums2);
console.log(nums);  //1,2,3,4,5,6,7,8,9

也可以这样理解nums调用了push方法,参数是通过apply将数组装换为参数列表的集合.

通常在什么情况下,可以使用apply类似Math.min等之类的特殊用法:

一般在目标函数只需要n个参数列表,而不接收一个数组的形式([param1[,param2[,…[,paramN]]]]),可以通过apply的方式巧妙地解决这个问题!

5.bind()

ECMAScript5还定义了一个方法:bind()。这个方法会创建一个函数的实例,其this值会被绑定到传给bind()函数的值。

window.color = "red";
var o = { color : "blue" };

function sayColor() {
    console.log(this.color);
}
var objectSayColor = sayColor.bind(o);        
//sayColor()调用bind()并传入对象o,并创建了objectSayColor函数。objectSayColor()函数的this值等于o

objectSayColor();        //blue

每个继承的toLocaleString()toString()方法始终都返回函数的代码。另外一个继承的valueOf()方法同样只返回函数代码。

5.6 基本包装类型

为了便于操作基本类型值,ECMAScript还提供了3个特殊的引用类型:BooleanNumberString。这些类型与本章介绍的其他引用类型相似,但同时也具有与各自的基本类型相应的特殊行为。实际上,每当读取一个基本类型值的时候,后台就会创建一个对应的基本包装类型的对象,从而让我们能够调用一些方法来操作这些数据。

var s1 = "some text";        //基本类型值
var s2 = s1.substring(2);    //调用了s1的substring()方法,结果保存s2

基本类型值不是对象,因而从逻辑上它们不应该有方法(但它们确实有方法)。其实,后台已经自动完成了一系列的处理。当第二行代码访问s1时,访问过程处于一种读取模式,也就是要从内存中读取这个字符串的值。而在读取模式访问字符串时,后台都会自动完成下列处理。
(1)创建String类型的一个实例;
(2)在实例上调用指定的方法;
(3)销毁这个实例。
可以将以上三个步骤想象成是执行了下列代码。

var s1 = new String("some text");    //创建String类型的一个实例;
var s2 = s1.substring(2);            //在实例上调用指定的方法;
s1 = null;                             //销毁这个实例。

经过此番处理,基本的字符串值就变得跟对象一样了。而且,上面的三个步骤也分别适用于BooleanNumber类型对于的布尔值和数字值。

引用类型与基本包装类型的主要区别就是对象的生存期。使用new操作符创建的引用类型的实例,在执行流离开当前作用域之前都一直保存在内存中。而自动创建的基本包装类型的对象,则只存在于一行代码的执行瞬间然后立即被销毁。这意味着我们不能在运行时为基本类型值添加属性和方法。

var s1 = "some text";
s1.color = "red";
alert(s1.color);   //undefined        第二行创建的String对象在执行这行时已经被销毁

对基本包装类型的实例调用typeof会返回"object",而且所有基本包装类型的对象都会被转换为布尔值的true

Object构造函数也会像工厂方法一样,根据传入值的类型返回相应的基本类型包装的实例。

var obj = new Object("some text");    //把字符串传给Object构造函数,就会创建String实例;而传入数值会得到Number的实例,传入布尔值参数就会得到Boolean的实例。
console.log(obj instanceof String);   //true

要注意的是,使用new调用基本包装类型的构造函数,与直接调用同名的转型函数是不一样的。例如:

var value = "25";
var number = Number(value);      //转型函数   变量number保存的是基本类型的值25
console.log(typeof number);   //number

var obj = new Number(value);  //构造函数   变量obj保存的是Number的实例
console.log(typeof obj);      //object

尽管不建议显式的创建基本包装类型的对象,但它们操作基本类型值的能力还是相当重要的。而每个2基本包装类型都提供了操作响应值的便捷方法。

5.6.1 Boolean类型

Boolean类型是与布尔值对应的引用类型。Boolean类型的实例重写了valueOf()方法,返回基本类型值true或false;重写了toString()方法,返回字符串"true"和"false"。

var falseObject = new Boolean(false);
var result = falseObject && true;        //布尔表达式中的所有对象都会被转换为true。因此表达式是true && true
console.log(result);                    //true

var falseValue = false;
result = falseValue && true;
console.log(result)                      //false

alert(typeof falseObject);                //object
alert(typeof falseValue);                 //boolean
alert(falseObject instanceof Boolean);  //true
alert(falseValue instanceof Boolean);   //false

建议永远不要使用Boolean对象

5.6.2 Number类型

Number是与数字值对于的引用类型。要创建Number对象,可以在调用Number构造函数时向其中传递相应的数值。

var numberObject = new Number(10);

与Boolean类型一样。Number类型也重写了valueOf()toLocaleString()toString()方法。重写后的valueOf()方法返回对象表示的基本类型数值,另外两个方法则返回字符串形式的数值。

Number类型还提供了一些用于将数值格式化为字符串的方法。

toFixed()

toFixed()方法会按照知指定的小数位返回数值的字符串表示:

var num = 10.005;
console.log(num.toFixed(2));  //"10.01"

能够自动舍入的特性,使得toFixed()方法很适合处理货币值。不同浏览器的给这方法的舍入规则可能会有所不同。

toExponential()

toExponential()方法返回以指数表示法(e表示法)表示的数值得字符串形式。toExponential()也接收一个参数,该参数也是指定输出结果中的小数位数。

var num = 10;
console.log(num.toExponential(1)); //"1.0e+1"
toPrecision()

对于一个数值来说,toPrecision()方法可能会返回固定大小(fixed)格式,也可能返回指数(exponential)的格式;具体规则是看哪种格式最合适。这个方法接收一个参数,即表示数值的所有数字的位数(不包含指数部分)。

var num = 99;
console.log(num.toPrecision(1));    //"1e+2"
console.log(num.toPrecision(2));    //"99"
console.log(num.toPrecision(3));    //"99.0"

与Boolean对象雷士,Number对象也以后台方式为数值提供了重要的功能。但与此同时,我们仍然不建议直接实例化Number类型,而原因与显式创建Boolean对象一样。具体来讲,就是在使用typeof和instanceof操作符测试基本类型数值与引用类型数值时,得到的结果完全不同,如下

var numberObject = new Number(10);
var numberValue = 10;
alert(typeof numberObject);               //"object"
alert(typeof numberValue);                  //"number"
alert(numberObject instanceof Number);  //true
alert(numberValue instanceof Number)    //false
5.6.3 String类型

String类型是字符串对象包装类型。可以使用String构造函数创建

var stringObject = new String("hello world");

String对象的方法也可以在所有基本的字符串值中访问到。其中,继承的valueOf()toLocaleString()toString()方法,都返回对象所表示的基本字符串值。

String类型每个实例都有一个length属性

var stringValue = "hello world";
console.log(stringValue.length); //"11"

String类型提供了很多方法,用于辅助完成对ECMAScript中字符串的解析和操作。

1. 字符方法

两个用于访问字符串中特定字符的方法是:charAt()charCodeAt()

var stringValue = "hello world";
console.log(stringValue.charAt(1));     //"e"   返回字符串1的位置的字符
console.log(stringValue.charCodeAt());  //"101" 返回字符串1的位置的字符编码
console.log(stringValue[1]);               //"e"   返回字符串1的位置的字符
2. 字符串操作方法

操作字符串的方法:

concat() 用于将以或多个字符串拼接起来

var stringValue "hello ";
var result = stringValue.concat("world", "!");  可以接收多个参数
console.log(result);        //"hello world"
console.log(stringValue);    //"hello"

ECMAScript还提供了三个基于子字符串创建新字符串的方法:slice()substr()substring()这三个方法都会返回被操作字符串的一个子字符串,而且也都接受一或两个参数。第一个参数指定子字符串的开始位置,第二个参数(在指定的情况下)表示字符串到哪结束。slice()substring()指第二个参数指定的是子字符串最后一个字符后面的位置。而substr()的第二个参数指定的则是返回的字符个数。如果没有给这些方法传递第二个参数,则将字符串的长度作为结束位置。这三个方法不会修改字符串本身的字——只返回一个基本类型的字符串字。

var stringValue = "hello world";
console.log(stringValue.slice(3));           //"lo world"
console.log(stringValue.substring(3));      //"lo world"
console.log(stringValue.substr(3));          //"lo world"
console.log(stringValue.slice(3, 7));          //"lo w"
console.log(stringValue.substring(3, 7));   //"lo w"
console.log(stringValue.substr(3, 7));       //"lo worl"

console.log(stringValue.slice(-3));               //"rld"           slice会将传入的负值和字符串想家
console.log(stringValue.substring(-3));          //"hello world"    substring会把所有负值转换为0
console.log(stringValue.substr(-3));              //"rld"           substr将负的第一个参数加上字符串的长度
console.log(stringValue.slice(-3, -4));          //"lo w"        
console.log(stringValue.substring(-3, -4));       //"hel"
console.log(stringValue.substr(-3, -4));           //""            转换为0等于包含0个字符串
3.字符串位置方法

indexOf() (从前往后)从一个字符串中搜索给定的子字符串,然后返回子字符串的位置。
- lastIndexOf() (从后往前)

4.trim()方法

ECMAScript5为所有字符串定义了trim()方法。这个方法会创建一个字符串的副本,删除前置及后缀的所有空额然后返回结果

trimLeft() 删除字符串开头空格

trimRight() 删除字符串末尾空格

5.字符串大小写转换方法

toLocaleUpperCase() —— 转换大写

toUpperCase() —— 转换大写

toLocaleLowerCase() —— 转换小写

toLowerCase() —— 转换小写

6.字符串的模式匹配方法

match()匹配

search()查找

replace()替换

split()分割字符串

7.localeCompare()方法

这个方法比较两个字符串

8.fromCharCode()方法

String构造函数本身还有一个静态方法。这个方法接收一或多个字符编码,然后把它转换为字符串。

5.7 单体内置对象

ECMA-262对内置对象的定义是:“由ECMAScript实现提供的、不依赖于宿主环境的对象,这些对象在ECMAScript程序执行之前就已经存在了”意思就是说,开发人员不必显式地实例化内置对象,因为它们已经实例化了。前面我们已经介绍了大多数的内置对象,例如Object、Array和String。ECMA-262还定义了两个单体内置对象:Global和Math。

注:每个内置对象(built-in object)都是原生对象(Native Object),一个内置的构造函数是一个内置的对象,也是一个构造函数。

5.7.1 Global对象

Global(全局)对象可以说是ECMAScript中最特别的一个对象了,因为你不管从什么角度看,这个对象都是不存在的。不属于任何其他对象的属性和方法,最终都是它的属性和方法。所有在全局作用域定义的属性和函数,都是Global对象的属性。诸如isNaN()isFinite()parseInt()以及parseFloat(),实际上全都是Global对象的方法

1.URI 编码方法

encodeURI()——编码

encodeURIComponent()——编码

encodeURI()——解码

encodeURIComponent()——解码

2.eval()方法

Javascript 的 eval 函数可以在当前作用域执行一段包含 Javascript 代码的字符串。
然而,eval 函数只有在当前作用域中直接被调用并且被调用的函数名为 eval 才会被执行。
eval 函数的使用应该被避免,99.9% 使用 eval 函数所实现的功能都可以通过不使用 eval 函数来实现。

eval 函数应该尽可能地避免使用。任何使用 eval 函数的代码都应该被质疑,远离eval

3.Global 对象的属性

特殊的值undefined、NaN以及Infinity都是Global对象的属性。所有原生引用类型的构造函数,象Object和Function,也都是Global对象的属性。

4.window 对象

ECMAScript虽然没有指出如何直接访问Global对象,但Web浏览器都是将这个全局对象作为window对象的一部分加以实现的。因此全局作用域中声明的所有变量和函数,就都成为了window对象的属性。

JavaScript中的window对象除了扮演ECMAScript规定的Global对象的角色外,还承担了很多别的任务。

另一种取得Global对象的方法:

var global = function(){
    return;
}
5.7.2 Math对象 1.Math对象的属性

Math对象包含的属性大都是数学计算中可能会用到的一些特殊值

2min()和max()方法

可以找到最大值max和最小值min
用于数组

var values = [1, 2, 3, 5, 4];
var max = Math.max.applu(null, values);  //5
3.舍入方法

Math.ceil() 执行向上舍入,即它总是将数值向上舍入为最接近的整数

Math.floor() 执行向下舍入,即它总是将数值向下舍入为最接近的整数

Math.round() 执行标准舍入,即它总是将数值四舍五入为最接近的整数

console.log(Math.ceil(25.9));   //26     ceil(25.5)——26    ceil(25.1)——26
console.log(Math.round(25.9));  //26     round(25.5)——26   round(25.1)——25
console.log(Math.floor(25.9));  //25     floor(25.5)——25   floor(25.1)——25
4.random()方法

随机数

值 = Math.floor(Math.random() * 可能值得总数 + 第一个可能的值)

//随机数1-10之间
var num = Math.floor(Math.random() * 10 + 1);
//2-10
var num = Math.floor(Math.random() * 9 + 2);

//计算数值
function selectFrom(lowerValue, upperValue) {
    var choices = upperValue - lowerValue + 1;
    return Math.floor(Math.random() * choices + lowerValue);
}
//2-10
var num = selectFrom(2, 10);

//随机抽取
var colors = ["red", "green", "blue"];
var color = colors[selectFrom(0, colors.lenght-1)];  //0到数组的长度

最后,如有错误和疑惑请指出,多谢各位大哥

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/82694.html

相关文章

  • javascript高程3 学习笔记(二)

    摘要:的理解函数与其他语言函数最大的不同在于,其不介意传入多少参数以及参数的类型比如函数的形参有两个,但是调用函数传入的参数可以写一个,三个或不写参数对应等,解析器都可以正常解析,这是因为中参数在内部是以一个数组形式来表示,故而不需要关系传入参数 ECMAScript function的理解 ECMAScript 函数与其他语言函数最大的不同在于,其不介意传入多少参数以及参数的类型...

    JerryWangSAP 评论0 收藏0
  • JS学习笔记(第4章)(变量、作用域和内存问题)

    摘要:具体来说就是当执行流进入下列任何一个语句时,作用域链就会得到加长语句的块和语句。这两个语句都会在作用域链的前端添加一个变量对象。对来说,会将指定的对象添加到作用域链中。 1. 基本类型和引用类型的值 JavaScript变量可以用来保存两种类型的值:基本类性值和引用类性值。基本类型值源自以下5种基本数据类型:Undefined、Null、Boolean、Number和String。基本...

    linkin 评论0 收藏0
  • JavaScript学习笔记 - 变量、作用域与内存问题

    摘要:语句中的块语句对来说,将会指定对象添加到作用域链中。在严格模式下,初始化未经声明的变量会导致错误。查询标识符搜索过程从作用域链的前端开始,向上逐级查询与给定名字匹配的标识符。 本文记录了我在学习前端上的笔记,方便以后的复习和巩固。 4.1基本类型和引用类型的值 ECMAScript变量可能包含两种不同数据类型的值:基本类型值和引用类型值。基本类型指的是简单的数据段,而引用类型值指那些可...

    lavnFan 评论0 收藏0
  • JavaScript学习笔记

    摘要:因为即使包含了其他的代码,也只会下载并执行属性内的外部脚本文件,嵌入的额外代码会被忽略。在脚本中,如果程序员在对某个变量赋值之前未声明,赋值操作将自动声明该变量。共有中数据类型。阻止事件冒泡火狐浏览器创建元素添加子元素删除子元素数组拼接方法 所有的web开发都是【请求】+【响应】 推荐JavaScript中使用单引号引用字符串,HTML中使用双引号,防止冲突 JavaScript代码...

    2shou 评论0 收藏0
  • 读书笔记:编写高质量javascript的68个方法

    摘要:第条尽量少使用全局对象避免声明全局变量尽量声明局部变量避免对全局变量增加属性第条始终声明局部变量第条避免使用语句第条熟练使用闭包的函数值包含了比调用他们时执行所需要的代码还要更多的信息。那些在其所涵盖的作用域内跟踪变量的函数称为闭包。 书还没看完。一遍看,一遍写读书笔记。 这本书的序是JavaScript之父Brendan Eich写的,作者是JavaScript标准化委员会专家。可想...

    Vicky 评论0 收藏0
  • JavaScript学习笔记整理:对象篇

    摘要:函数式对象的一个子类型,中的函数是一等公民内置对象中还有一些对象子类型,通常被称为内置对象。内容对象的内容是由一些存储在特定命名位置的任意类型的值组成的,我们称之为属性。 语法 对象两种定义形式 声明(文字)形式 构造形式 //声明(文字)形式 var myObj = { key: value // ... } //构造形式 var myObj = new Ob...

    testbird 评论0 收藏0

发表评论

0条评论

dendoink

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<