JavaScript高级程序设计——第5章 引用类型

引用类型的值(对象)是引用类型的一个实例。ECMAScript中,引用类型是一种数据结构,也称为对象定义。

5.1 Object类型

创建Object实例的两种方法
* new Object()

var person = new Object();
person.name = "Jane";
person.age = 16;
  • 对象字面量表示法
var person = {
    name: "Jane", //注意逗号
    age: 16
}; //注意分号

对象字面量语法的属性名可以是字符串

var person = {
    "name": "Jane", //注意逗号
    "age": 16
}; //注意分号
  • 访问对象属性
var person = {
    "name": "Jane",
    "age": 16,
    "first name":"Black"
};
console.log(person.name);
console.log(person["name"]);
console.log(person["first name"]);
//console.log(person.first name) 错误

5.2 Array类型

//Array构造函数
var color1 = new Array(20);
var color2 = new Array("red","blue","green");
var color3 = Array("yellow");//可以省略new操作符

//字面量表示法
var color4 = ["yellow","grey"];

//length属性
console.log(color2.length); //3

//利用length属性可以修改数组末尾
color4.length = 1;
console.log(color3[1]); //undefined

color4.length = 2;
console.log(color4); //[ 'yellow',  ]
5.2.1 检测数组
var color1 = Array("red");
var color2 = Array("green");

console.log(color1 instanceof Array); //假定只有一个全局执行环境
console.log(Array.isArray(color2));
5.2.2 转换方法
  • toString()
    创建数组值的以逗号分隔的字符串,toString()方法获取的是String(传统字符串),对数组每个值调用toString()

  • toLocaleString()
    创建数组值的以逗号分隔的字符串,toLocaleString()方法获取的是LocaleString(本地环境字符串),对数组每个值调用toLocaleString()。

  • valueOf()
    输出对象本身的值

var obj1 = [1,1,1];
var obj2 = [2,2,2];
var obj3 = [obj1,obj2];
obj1.toString = "obj1";
obj2.toString = "obj2";
//console.log(obj3.toString()); //报错
console.log(obj3.toLocaleString()); //1,1,1,2,2,2
console.log(obj3.valueOf()); //[ [ 1, 1, 1, toString: 'obj1' ], [ 2, 2, 2, toString: 'obj2' ] ]
  • join()方法
    无参数,或传入undefined时,使用逗号分隔符。
var arr = ["red","green","blue"];
console.log(arr.join()); //red,green,blue
console.log(arr.join("||")); //red||green||blue
5.2.3 栈方法
  • push()
    接受任意数量的参数,逐个推入数组末尾,返回修改后数组的长度
  • pop()
    从数组末尾移除最后一项,length - 1,返回移除的项
var count = arr.push("grey"); 
console.log(count);           //4
console.log(arr);             //[ 'red', 'green', 'blue', 'grey' ]
var item = arr.pop();        
console.log(item);            //grey
console.log(arr);             //[ 'red', 'green', 'blue' ]
5.2.4 队列方法
  • shift()
    移除数组的第一个项并返回该项,length - 1.
  • unshift()
    在数组前端添加任意个项并返回新数组长度。
    push() + shift() 队列操作
    pop() + unshift() 反向队列操作
5.2.5 重排序方法
  • sort()
    调用每个数组项的toString()方法,然后比较得到的字符串。
var values =[1,2,10,5,3,11,4];
console.log(values.sort()); //[ 1, 10, 11, 2, 3, 4, 5 ]

为了得出数值比较顺序,可以接受一个比较函数,确定排序方法
比较函数:比较函数接受两个参数,如果第一个数应该位于第一个参数之前则返回负数,如果两个参数相等则返回0,如果第一个参数应该在第二个参数之后则返回正数。下面是一个升序排列。

function compare(value1,value2){
    if(value1 < value2){
        return -1;
    }
    else if(value1 > value2){
        return 1;
    }
    else return 0;
}
console.log(values.sort(compare)); //[ 1, 2, 3, 4, 5, 10, 11 ]

对于数值类型或者valueOf会返回数值类型的对象类型,可以使用以下一个简单的比较函数

function compare1(value1,value2){
    return value1 - value2;
}
  • reverse() 反转数组
5.2.6 操作方法
  • concat() 基于当前数组所有项创建一个新数组:先创建当前数组的副本,然后将接受到的参数添加到这个数组的末尾,最后返回新数组,无参数情况下只是复制当前数组并返回副本。如果传递给concat()的是多个数组,它会把数组的每一项都添加到结果数组中
var origin =["red","green","blue"];
var result = origin.concat("yellow",["grey","pink"]);
console.log(origin); //[ 'red', 'green', 'blue' ]
console.log(result); //[ 'red', 'green', 'blue', 'yellow', 'grey', 'pink' ]

  • slice() 基于当前数组中的一或多个项创建一个数组,不影响原数组。语法
    arrayObject.slice(start,end)
参数描述
start必需。规定从何处开始选取。如果是负数,那么它规定从数组尾部开始算起的位置。也就是说,-1 指最后一个元素,-2 指倒数第二个元素,以此类推。
end可选。规定从何处结束选取。该参数是数组片断结束处的数组下标。end下标的项会被截取。如果没有指定该参数,那么切分的数组包含从 start 到数组结束的所有元素。如果这个参数是负数,那么它规定的是从数组尾部开始算起的元素。
var array = [1,2,3,4,5,6,7,8,9,10];
console.log(array.slice(1));   //[ 2, 3, 4, 5, 6, 7, 8, 9, 10 ]
console.log(array.slice(-2));  //[ 9, 10 ]
console.log(array.slice(3,5)); //[ 4, 5 ]

其实,slice()中参数的负数是这样处理的:数组长度加上该负数,确定相应的位置。

如上面array.slice(-2)等价于array.slice(10-2);如果转换后start > end,返回空数组。

  • splice() 主要用途是在数组中部插入项,返回一个数组,其中包含从原始数组删除的项。(没有删除,返回空数组)语法:
    arrayObject.splice(index,howmany,item1,…..,itemX)
参数描述
index必需。整数,规定添加/删除项目的位置,使用负数可从数组结尾处规定位置。
howmany必需。要删除的项目数量。如果设置为 0,则不会删除项目。
item1, …, itemX可选。向数组添加的新项目。
var array = [1,2,3,4,5,6,7,8,9,10];
var remove = array.splice(0,2);
console.log(array);  //[ 3, 4, 5, 6, 7, 8, 9, 10 ]
console.log(remove); //[ 1, 2 ]

array.splice(3,0,2,2);
console.log(array);  //[ 3, 4, 5, 2, 2, 6, 7, 8, 9, 10 ]

5.2.7 位置方法
  • indexOf() 返回某个指定的字符串值在字符串中首次出现的位置。lastIndexOf()类似,但是是从数组末尾往前开始查找
    stringObject.indexOf(searchvalue,fromindex)
参数描述
searchvalue必需。规定需检索的字符串值。
fromindex可选的整数参数。规定在字符串中开始检索的位置。它的合法取值是 0 到 stringObject.length - 1。如省略该参数,则将从字符串的首字符开始检索。

注:要求查找项严格相等。

var str="Hello world!"
console.log(str.indexOf("Hello "));  //0
console.log(str.indexOf("l"));       //2
console.log(str.lastIndexOf("l"));   //9
console.log(str.indexOf("world"));   //6
5.2.8 迭代方法

以下方法都不修改原数组

方法描述
every()对数组中的每一项运行给定函数,如果该函数对每一项都返回true,则返回true
some()对数组中的每一项运行给定函数,如果该函数对任一项都返回true,则返回true
filter()对数组中的每一项运行给定函数,返回该函数会返回true的项组成的数组
forEach()对数组中的每一项运行给定函数,没有返回值
map()对数组中的每一项运行给定函数,返回每次函数调用的结果组成的数组

以every方法为例子:arr.every(callback[, thisArg])
* callback:Function to test for each element, callback(currentValue,index,array) taking three arguments:

parameterdescription
currentValue (required)The current element being processed in the array.
index (optional)The index of the current element being processed in the array.
array (optional)The array every was called upon.

* thisArg:Optional. Value to use as this when executing callback.If a thisArg parameter is provided to every, it will be used as callback’s this value. Otherwise, the value undefined will be used as its this value.

var arr = [3,4,5,1,6,7,8,9];
var result1 = arr.every(function (item){
    return (item > 2);
});
console.log(result1); //false
//加上index thisArg
var thisArg = "this";
var result2 = arr.every(function (item,index,array){
    console.log(index);
    console.log(this);
    return (item > 2);
},thisArg);
//依次输出:
/***
0
[String: 'this']
1
[String: 'this']
2
[String: 'this']
3
[String: 'this']
 ***/
console.log(result2); //false
5.2.9 归并方法
  • > reduce()
    arr.reduce(callback[, initialValue])
  • callback:Function to execute on each element in the array,callback(accumulator,currentValue,CurrentIndex,Array) taking four arguments:
parameterdescription
accumulatorThe accumulator accumulates the callback’s return values; it is the accumulated value previously returned in the last invocation of the callback, or initialValue, if supplied
currentValueThe current element being processed in the array.
currentIndexThe index of the current element being processed in the array. Starts at index 0, if an initialValue is provided, and at index 1 otherwise.
arrayThe array reduce was called upon.

* initialValue
[Optional] Value to use as the first argument to the first call of the callback. If no initial value is supplied, the first element in the array will be used. Calling reduce on an empty array without an initial value is an error.

var arr = [1,2,3,4,5,6];
var initialValue = 9;
var result = arr.reduce(function(prev,cur,index,array){
    console.log('现在正在操作项的下标:',index);
    return prev.toString().concat(cur);
},initialValue);
console.log(result);
/****
 现在正在操作项的下标: 0
 现在正在操作项的下标: 1
 现在正在操作项的下标: 2
 现在正在操作项的下标: 3
 现在正在操作项的下标: 4
 现在正在操作项的下标: 5
 9123456
 ****/
  • > reduceRight() 从数组最后一项开始

5.3 Date类型

ECMAScript的Date类型使用UTC(Coordinated Universal Time)1970年1月1日零时开始经过的毫秒数来保存时间。
创建一个Date对象:

var now = new Date();  //不传入参数,自动获取当前时间

如果想根据特定日期和时间创建日期对象,必须传入该日期的毫秒数(从UTC时间1970年1月1日零时至该日期),为了简化这一过程,有两个方法:
* Date.parse()

Direct call:

Date.parse(dateString)

Implicit call:

new Date(dateString)

The Date.parse() method parses a string representation of a date, and returns the number of milliseconds since January 1, 1970, 00:00:00 UTC or NaN if the string is unrecognized or, in some cases, contains illegal date values (e.g. 2015-02-31).

It is not recommended to use Date.parse as until ES5, parsing of strings was entirely implementation dependent. There are still many differences in how different hosts parse date strings, therefore date strings should be manually parsed (a library can help if many different formats are to be accommodated).

var date1 = new Date("6/13/2004");                        //2004-06-12T16:00:00.000Z
var date2 = new Date("Jan 12,2014");                      //2014-01-11T16:00:00.000Z
var date3 = new Date("Tue May 25 2004 00:00:00 GMT-0700");//2004-05-25T07:00:00.000Z
var date4 = new Date("2009-05-25T00:00:00");              //2009-05-25T00:00:00.000Z

* Date.UTC()
Date.UTC(year, month[, day[, hour[, minute[, second[, millisecond]]]]])

parameterdescription
yearA year after 1900.
monthAn integer between 0 and 11 representing the month.
dayOptional. An integer between 1 and 31 representing the day of the month.
hourOptional. An integer between 0 and 23 representing the hours.
minuteOptional. An integer between 0 and 59 representing the minutes.
secondOptional. An integer between 0 and 59 representing the seconds.
millisecondOptional. An integer between 0 and 999 representing the milliseconds.
var date1 = new Date(Date.UTC(2000,0,1,14,55,55)); //2000-01-01T14:55:55.000Z
5.3.1 继承的方法

Date类型也重写了toLocaleString() toString() valueOf()方法,返回值如下

方法返回值
toLocaleString()按照与浏览器设置的地区相适应格式返回日期和时间
toString()返回带有时区信息的日期和时间
valueOf()
5.3.2 日期格式化方法

将日期转换为字符串的方法(输出的字符串因浏览器而异):

image.png

5.4 RegExp类型

语法:var expression = / pattern / flags ;

flags描述
g全局(global)模式,模式将被应用于所有字符串,而非在发现第一个匹配项的时候停止
i不区分大小写,case-insensible
m多行模式,multiline,在到达一行末尾时还会继续查找下一行是否存在匹配项
uUnicode,将模式视为Unicode序列点的序列
y粘性匹配; 仅匹配目标字符串中此正则表达式的lastIndex属性指示的索引(并且不尝试从任何后续的索引匹配)

* 字面量形式

var pattern1 = /at/g;        //匹配所有“at”实例
var pattern2 = /[bc]at/i;    //匹配第一个bat或cat,不区分大小写
var pattern3 = /\[bc\]at/i;  //匹配第一个[bc]at,不区分大小写
  • RegExp构造函数:传递的两个参数都是字符串
var pattern2 = RegExp("[bc]at","i");   //匹配第一个bat或cat,不区分大小写
var pattern3 = RegExp("\[bc\]at","i"); //匹配第一个[bc]at,不区分大小写

注:使用字面量方法始终共享一个RegExp实例,而构造函数每次创建的每一个新的RegExp实例都是新的。
特殊字符的含义

5.4.1 RegExp实例属性
属性描述
global布尔值,是否设置g标志
ignoreCase布尔值,是否设置i标志
lastIndex整数,表示开始搜索下一个匹配项的字符位置
multiline布尔值,是否设置m标志
source正则表达式的字符串表示,按照字面量形式传入
5.4.2 RegExp实例方法
methoddescription
exec()The exec() method executes a search for a match in a specified string. Returns a result array, or null
test()The test() method executes a search for a match between a regular expression and a specified string. Returns true or false.
toString()The toString() method returns a string representing the regular expression.
// Match "quick brown" followed by "jumps", ignoring characters in between
// Remember "brown" and "jumps"
// Ignore case
var re = /quick\s(brown).+?(jumps)/ig;
var result = re.exec('The Quick Brown Fox Jumps Over The Lazy Dog');
console.log(result);
/*
[ 'Quick Brown Fox Jumps',
  'Brown',
  'Jumps',
  index: 4,
  input: 'The Quick Brown Fox Jumps Over The Lazy Dog' ]
 */

下表列出这个脚本的返回值:

image.png

5.5 Function类型

  • > 函数名实际上是一个指向函数的对象的指针,不会与某个函数绑定
function fun(num1,num2){
    return num1 + num2;
}
console.log(fun(2,3));  //5
var fun = function(num1,num2){
    return num1 - num2;
};
console.log(fun(2,3)); //-1
var fun = new Function("num1","num2","return num1 * num2"); //函数表达式,不推荐
console.log(fun(2,3)); //6

第三种命名方法虽不建议,但是有助于理解函数是对象,函数名是指针这一概念。
同时,在例子中也可以看到,后面声明的同名函数会覆盖前面的,这也印证了js**没有重载**这一点。
* > 解析器在执行环境中加载数据时,率先解读函数声明,使其在其执行环境任何代码之前可用;执行到函数表达式所在行,才解析函数表达式
* > 函数内部属性
* arguments对象
arguments对象有一个属性,callee,该属性是一个指针,指向拥有这个arguments对象的函数。
例子:解除函数的执行和函数名的紧耦合

function factorial(num){
    if(num <= 1){
        return 1;
    }
    else{
        return num * arguments.callee(num - 1);
    }
}
var tureFactorial = factorial;
factorial = function(){
    return 0;
};
console.log(tureFactorial(5));  //120
console.log(factorial(5));       //0

即使后面factorial指针指向另一个函数,阶乘函数在执行时由于没有紧密耦合原函数,故能正确执行。
* this对象
this对象引用的是函数据以执行的环境对象。无论是否在严格模式下,在全局执行上下文中(在任何函数体外部)this都指代全局对象。
* caller属性
保存调用当前函数的函数的引用

function outer(){
    inner();
}
function inner(){
    console.log(inner.caller);
}
outer();  //[Function: outer]
  • > 函数属性和方法
  • length:函数希望接受的命名参数的个数
  • prototype:保存所有实例方法的真正所在
  • apply()、call():在特定的作用域中调用函数
// 一个对象可以作为call和apply的第一个参数,并且this会被绑定到这个对象。
var obj = {a: 'Custom'};

// 这个属性是在global对象定义的。
var a = 'Global';

function whatsThis(arg) {
    return this.a;  // this的值取决于函数的调用方式
}

whatsThis();          // 直接调用,      返回'Global'
whatsThis.call(obj);  // 通过call调用,  返回'Custom'
whatsThis.apply(obj); // 通过apply调用 ,返回'Custom'
  • bind()方法
    ECMAScript 5 引入了 Function.prototype.bind。调用f.bind(某个对象)会创建一个与f具有相同函数体和作用域的函数,但是在这个新函数中,this将永久地被绑定到了bind的第一个参数,无论这个函数是如何被调用的。
function f(){
  return this.a;
}

//this被固定到了传入的对象上
var g = f.bind({a:"azerty"});
console.log(g()); // azerty

var h = g.bind({a:'yoo'}); //bind只生效一次!
console.log(h()); // azerty

var o = {a:37, f:f, g:g, h:h};
console.log(o.f(), o.g(), o.h()); // 37, azerty, azerty

5.6 基本包装类型

3个特殊的引用类型:Boolean、Number和String。
每当读取一个基本类型值时,后台就会创建一个对应的基本包装类型的对象,从而让我们能够调用一些方法来操作这些数据。

var s1 = "text"; 
var s2 = s1.substring(2);

变量s1包含一个字符串,为基本类型值,但是它不是对象,讲道理不应该有方法。后台为了实现第二行代码(读取模式访问字符串),自动完成下列处理:
①创建String类型的一个实例
②在这个实例上调用指定方法
③销毁这个实例
可以将这个过程想象成下面的代码

var s1 = new String("text");
var s2 = s1.substring(2);
s1 = null;

以上这三个步骤也适合Boolean和Number类型值。
注:自动创建的基本包装类型的对象,只存在于一行代码执行的瞬间,然后立刻被销毁。所有不能再运行时为基本类型值添加属性和方法。

5.7 单体内置对象

ECMA-262对内置对象的定义:有ECMAScript实现提供的、不依赖宿主环境的对象,这些对象在ECMAScript程序执行之前就已经存在了。

Global对象

  • URI编码方法

Global对象的encodeURI()和encodeURIComponent()方法可以对URI(Uniform Resource Identifiers,通用资源标识符)进行编码,以便发送给浏览器。encodeURI()不会对本身属于URI的特殊字符进行编码,例如冒号、正斜杠、问号和井号;例子中只对空格进行编码。encodeURIComponent()对所有非标准字符进行编码。

var uri = "https://developer.mozilla.org/zh CN #/";
console.log(encodeURI(uri));          //https://developer.mozilla.org/zh%20CN%20#/
console.log(encodeURIComponent(uri)); //https%3A%2F%2Fdeveloper.mozilla.org%2Fzh%20CN%20%23%2F

与这两个方法对应的有decodeURI()和decodeURIComponent(),decodeURI()只能对使用encodeURI()替换的字符进行编码,decodeURIComponent()只能对使用encodeURIComponent()替换的字符进行编码。

var uri = "https%3A%2F%2Fdeveloper.mozilla.org%2Fzh%20CN%20%23%2F";
console.log(decodeURI(uri));          //https%3A%2F%2Fdeveloper.mozilla.org%2Fzh CN %23%2F
console.log(decodeURIComponent(uri)); //https://developer.mozilla.org/zh CN #/
  • eval()方法

只接收一个参数,即要执行的ECMAScript或JavaScript字符串。解析器会将eval()传入的参数当做实际的语句来解析,然后把执行结果插入到原位置。通过eval()执行的的代码被认为是饱含该次调用的执行环境的一部分,被执行的代码具有与该执行环境相同的作用域链。
* Global对象的属性
* window对象

Math对象

  • 属性:一些数学计算可能用到的数值,如Math.E(自然对数的底e)、Math.SQRT2(2的平方根)。
    *min()&max():确定一组数值中的最大/最小值。
var max  = Math.min(1,5,63,42); //1
  • 舍入方法
方法描述
Math.ceil()向上舍入,将数值舍入为最接近的整数
Math.floor()向下舍入,将数值舍入为最接近的整数
Math.round()四舍五入

* random()方法:返回[0,1)之间的一个随机数

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值