JavaScript高级程序设计——第五章(引用类型)

一.前言

本章继续进行引用类型的深入学习,将引用类型分成几个组成部分,涉及多种类型的属性,方法的使用,需要重点了解学习。

二.Object类型

1.写法

var person = new Object();
person.name = 'nico'
person.age = 18

②对象字面量

var person = {
	name : 'nico',
	age : 18
}

2.获取对象属性的方法

alert(person['name'])  //'nico'
alert(person.name)  //'nico'

从功能上看,这两种方法没有任何区别,但是方括号语法的优点是可以通过变量来访问属性,导致语法错误的字符也可以使用,比如:

person['first name'] = 'nico'

‘first name’之间包含了一个空格,所以不能用点表示法来访问它,这时方括号表示法就可以正确的表示。

三.Array类型

1.写法

var names = new Array(3) //创建一个包含三项的数组
var colors = new Array('nico')  //创建一个一项,即字符串‘nico’的数组

var colors = ['red','blue']

2.length属性
数组的length属性很有特点——它不是只读的

var colors = ['red','blue','green']  //创建一个包含三个字符串的数组
colors.length = 4;
alert(colors[3])  //undefined

新增的每一项为undefined

var colors = ['red','blue','green']  //创建一个包含三个字符串的数组
colors.length = 2;
alert(colors[2])  //undefined

改变length移除了最后一项,访问不存在的值会出现undefined。

也可以通过索引改变length的长度

var color = ['blue','green']
color[99] = 'pink'
alert(color.length) //100

但是位置2-99都是不存在的,均为undefined。

3.监测方法
①之前我们提到过instanceof可以检测对象类型,这里当然可以检测数组

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

instanceof的问题在于:它假定只有一个全局环境,如果网页中包含多个框架,那实际上就存在两个以上不同的全局环境,那么就会存在两个不同版本的Array构造函数。


为了解决这个方法,新增了**Array.isArray()**方法

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

4.转换方法
①toString()
toString()方法会返回数组中每个值的字符串形式拼接而成的一个以逗号分隔的字符串。

var colors = ['red','blue','pink']
alert(colors.toString())  //red,blue,pink

②valueOf()
valueOf()方法直接返回数组本身。

③toLocaleString()
它也会创建一个以逗号分隔的字符串来表示数组,与toString()不同的是,这里的方法是toLocaleString()而不是toString(),他们是两种不同的方法,只不过转换为相同的结果了。

④join
如果想用不同的分隔符表示

var colors = ['red','blue','pink']
alert(colors.join('||'))  //red || blue || pink

5.栈方法
push()和pop():push()是在数组最后推入一个参数,pop()是从数组末尾移除最后一项。

6.队列方法
shift()和unshift():shift()是将数组第一项推出,unshift()是在数组前端添加任意项。

7.重排序方法
①reverse():该方法会反转数组的顺序。
②sort():**该方法先调用每个数组项的toString()方法,然后比较得到的字符串。**正因为如此,sort()支持自定义排序,可以接受一个比较函数进行排序。

function compareArr(value1,value2){
	if(value1 < value2){
		return -1
	}else if(value1 > value2){
		return 1;
	}else{
		return 0;
	}
}
var values = [0,1,5,10,15];
values.sort(compareArr);
alert(values)  //0,1,5,10,15

8.操作方法
①concat
**这个方法会先创建当前数组的一个脚本,然后将接收到的参数添加到这个脚本的末尾,最后返回新构建的数组。**如果参数是数组,则将数组的每一项都添加到结果数组中。

var colors = ['red','blue']
var colors2 = colors.concat('yellow',['black','brown'])
alert(colors2)  //['red','blue','yellow','black','brown']

②slice
slice()可以接受1或者2个参数,只有一个参数的情况,slice()返回从该参数位置开始到数组末尾结尾的所有项。如果是两个参数,该方法返回起始和结束位置之间的项——但不包括结束位置的项。

var colors = ['red','blue','green','yellow'];
var colors2 = colors.slice(1);
var colors3 = colors.slice(1,3)

alert(colors2)  //['blue','green','yellow']
alert(colors3)  //['blue','green']

如果slice()的参数中有负数,则用数组的长度加上该数来确定相应的位置。
silce(-2,-1)与slice(2,3)得到接结果相同。

③splice()
splice()的用法很多,功能很强大,主要有以下三种用法:

  1. 删除:可以删除任意项,只需指定两个参数,要删除的第一项的位置和要删除的项数。
var colors = ['red','green','blue']
var removed = colors.splice(0,1)
alert(colors)  //['green','blue']
alert(removed)  //['red']

2.插入:可以向指定位置插入任意数量的项,只需提供三个参数:起始位置,0(要删除的项数),要插入的项。要插入多个项的话,可以继续传第四个第五个…任意多个项。

var colors = ['red','green','blue']
var removed = colors.splice(1,0,'yellow','orange')

alert(colors)  //['red','yellow','orange','green','blue']
alert(removed)  //返回的是空数组

3.替换:可以向指定位置插入任意数量的项,且同时删除任意数量的项,只需提供三个参数:起始位置,要删除的项数,要插入的任意数量的项。

var colors = ['red','green','blue']
var removed = colors.splice(1,1,'yellow','orange')

alert(colors)  //['red','blue','yellow','orange']
alert(removed)  //['green']

9.位置方法
indexOf()和lastIndexOf(),这两个方法都接受两个参数,要查找的项和表示查找起点的索引。indexOf()方法从数组开头开始向后查找,lastIndexOf()方法则从数组的末尾开始向前查找。

var numbers = [1,2,3,4,5,6,4,3,2,1];
alert(numbers.indexOf(4))  //3
alert(numbers.lastIndexOf(4))  //6

10.迭代方法(重点)

ECMAScript为数组定义了5个迭代方法,每个方法接受两个参数:要在每一项上运行的函数(可选)和运行该函数的作用域对象——影响this指向。
传入这些方法中的函数会接受三个参数:数组项的值,该和在数组中的位置和数组对象本身。
①every():对数组中每一项运行给定函数,如果该函数对每一项返回true,则返回true。

var numbers = [1,2,3,4,5,6,7]
var everyNumber = numbers.every(function(item,index,array){
	return (item > 2)
})

alert(everyNumber)  //false(因为数组中不是每一项都>2)

②filter():对数组中每一项运行给定函数,返回该函数会返回true的项组成的数组。

var numbers = [1,2,3,4,5,6,7]
var filterNumber = numbers.filter(function(item,index,array){
	return (item > 2)
})

alter(filterNumber)  //[3,4,5,6,7]

③forEach():对数组中每一项运行给定函数,这个方法没有返回值。

var number = [1,2,3,4,5,4,3,2,1];
number.forEach(function(item,index,array){
	.....//你想进行的操作
})

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

var number = [1,2,3,4,5,4,3,2,1];
var mapNumber = number.map(function(item,index,array){
	return item * 2;
})
alert(mapNumber)  //[2,4,6,8,10,8,6,4,2]

⑤some():对数组中每一项运行给定函数,如果函数对任意一项返回为true,则返回true。

var number = [1,2,3,4,5,4,3,2,1];
var someNumber = number.some(function(item,index,array){
	return (item > 2);
})
alert(mapNumber)  //true

11.归并方法
reduce()和reduceRight(),这两种方法都会迭代数组的所有项,然后构建一个最终返回的值。reduce()是从数组的第一项开始,遍历数组到最后。reduceRight()是从数组最后一项开始,遍历数组到第一项。
这两个方法接受两个参数:一个是每一项调用的函数,另一个是作为归并基础的初始值。其中函数接受四个参数:前一个值,当前值,项的索引和数组对象。第一个参数是数组的第一项,第二个参数是数组的第二项,以此类推。

var values = [1,2,3,4,5];
var sum = values.reduce(function(prev,cur,index,array){
	return prev + cur
});
alert(sum);  //15

四.Date类型

要为2020年4月14日创建一个日期对象:

var someData = new Date(Date.parse('April 14, 2020'));

五.RegExp类型

详情见书

六.Function类型

函数实际上也是对象。函数名实际上就是指向函数对象的指针。我们写个代码案例说明:

function sum(num1,num2){
	return num1 + num2
}
alert(sum(10,10));  //20

var anotherSum = sum
alert(anotherSum(10,10))  //20

sum = null
alert(anotherSum(10,10))  //20

使用不带圆括号的函数名是访问函数指针,此时sum和anotherSum指向了同一个函数,因此anotherSum()可以调用并返回结果,即使将sum设置为null,也不会影响anotherSum的正常调用。

函数声明与函数表达式

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

上面的代码可以正常执行,因为在代码开始执行之前,解析器就通过一个函数声明提升的过程,读取并将函数声明添加到执行环境中。如果换一种写法:

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

则会报错,因为函数位于一个初始化语句中,而不是一个函数声明。第一行就会报错。除此之外,函数声明与函数表达式的语法其实是等价的

③函数内部属性

  1. callee

    我们之前说过函数内部有一个arguments属性,包含传入函数中的所有参数。这个对象还有一个名叫callee的属性,该属性是一个指针,指向拥有这个arguments对象的函数。

    function factorial(num){
    	if(num <= 1){
    		return 1;
    	}else{
    		return num * factorial(num - 1)
    	}
    }
    

    这是一个阶乘函数,用到的是递归算法,但是这种写法执行的函数与函数名紧紧的耦合在了一起,为了消除不必要的影响。

    function factorial(num){
    	if(num <= 1){
    		return 1;
    	}else{
    		return num * arguments.callee(num - 1)
    	}
    }
    

    这样定义的话,就算将factorial这个函数复制给别的函数,也一样可以实现功能。

  2. caller
    这个属性中保存着调用当前函数的函数的调用。

    function outer(){
    	inner()
    }
    function inner(){
    	alter(inner.caller)  //弹出的是outer的源代码
    }
    outer()
    

    outer()调用了inner(),所以会弹出outer()的源代码。

    为了实现更加松散的耦合,下面代码是一个意思:

    function outer(){
    		inner()
    	}
    	function inner(){
    		alter(argument.callee.caller)  //弹出的是outer的源代码
    	}
    	outer()
    

函数属性和方法

每个函数包含两个属性:

  1. length
    length属性表示该函数希望接收的参数的个数。

  2. prototype
    prototype是保存函数所有实例的真正地方所在。

每个函数都包含两个非继承而来的方法:用途都是在特定的作用域中调用函数。

  1. apply()
    apply()接收两个参数,一个是在其中运行函数的作用域,另一个是参数数组
function sum(num1,num2){
	return num1 + num2
}
function applySum(num1,num2){
	return sum.apply(this,[num1,num2])
}
alert(applySum(10,10));  //20

这里applySum本身没有进行数值操作,**但是apply()里面的第一个参数this指向的是applySum(apply改变了sum中的this指向)**后面以数组形式传参,利用sum函数得到结果。

  1. call()
    call()与apply()方法的作用相同,区别在于接收参数的方式不同。使用call()方法时,要把 必要的参数一个一个列出来。
function sum(num1,num2){
	return num1 + num2
}
function callSum(num1,num2){
	return sum.call(this,num1,num2)
}
alert(callSum(10,10));  //20

这两个方法真正强大的地方在于扩充函数赖以运行的作用域。

window.color = 'red'

var o = {
	color:'blue'
}
function sayColor(){
	alert(this.color)
}

sayColor()   //red
sayColor.call(o)  //blue
function add(a, b) {
    return a + b;
}

function sub(a, b) {
    return a - b;
}

console.log(add.call(sub, 2, 1));  //3

七.基本包装类型

为了便于操作基本类型值,ECMAScript提供了3个特殊的引用类型:Boolean,Number,String

  1. Boolean
var booleanObject = new Boolean(true)
var booleanValue = false

alert(typeOf booleanObject)  //object
alert(typeOf booleanValue)  //boolean

alert(booleanObject instanceof Boolean)  //true
alert(booleanValue instanceof Boolean)  //false

基本类型和引用类型的布尔值有两个区别:typeOf()基本类型是boolean,引用类型是object,boolean对象是boolean类型的实例,所以使用instanceof返回true,基本类型则返回false。

  1. Number
    ①将数值格式化为字符串的方法
var num = 10
alert(num.toFixed(2))  //'10.00'

②同上述Boolean相同,typeOf()和instanceof也有类似特征。

  1. String
    ①两个访问字符串中特定字符的方法:charAt()和charCodeAt()。
var stringValue = 'hello world'
alert(stringValue.charAt(1));  //e  返回位置是1的字符
alert(stringValue.charCodeAt(1))  //'101'  返回该字符对应的字符编码

②字符串操作方法

  1. concat()
    用于拼接多个字符串,但是一般我们用‘+’更加方便简洁。

  2. slice() substr() substring() 详情见书

  3. indexOf()和lastIndexOf()。
    用于从字符春中查找子字符串。

var stringValue = 'hello world'
alert(stringValue.indexOf('o'))  //4
alert(stringValue.lastIndexOf('o'))  //7
  1. trim()
    该方法会创建一个字符串的副本,删除前置及后缀所有空格,然后返回结果。
var stringValue = ' hello world '
var trimStringValue = stringValue.trim()
alert(trimStringValue)  //'hello world'
  1. 字符串大小写转换方法
var stringValue = 'hello world'
alert(stringValue.toUpperCase())  //'HELLO WORLD'
alert(stringValue.toLowerCase())  //'hello world'

八.单体内置对象

  1. Global对象
    所有在全局作用域中定义的属性和函数,都是Global对象的属性。
    存在一个**eval()**方法:它只接收一个参数,就是要执行的字符串。
    它将传入的参数当作实际的代码进行解析,被执行的代码拥有执行环境相同的作用域。

我们要做一个function(),功能是输入网页中两个个对象的名称,然后程序就将这两个对象的值联接起来输出。

function output(a,b){
     var tmpa,tmpb;
     tmpa=document.all.a.value;
     tmpb=document.all.b.value;
     document.write(tmpa+tmpb);
}
output('input1','input2');
        这样你执行的时候就会提示错误“document.all.a不是对象”以及“document.all.b不是对象”。原来javascript把a和b当成对象名称了,怎样能让javascript把a里面的值作为对象名称呢?这时候就要用eval了,把代码改成这样:
 function output(a,b){
	var tmpa,tmpb;
	tmpa=eval("document.all."+a+".value");
	tmpb=eval("document.all."+b+".value");
	document.write(tmpa+tmpb);
  }
  output('input1','input2');
        这样javascript就会先取出a,b的值,然后和前面的document.all.以及后面的.value组合运行,于是就可以顺利取出input1和input2的值。
  1. Math()对象
    Math().ceil:执行向上舍入,将数值向上舍入为最接近的整数。
    Math().ceil:执行向下舍入,将数值向下舍入为最接近的整数。
    Math().ceil:执行向上舍入,将数值向上舍入为最接近的整数。
    Math().ceil:执行标准舍入,将数值四舍五入为最接近的整数。

    Math().random:返回大于等于0小于1的一个随机数。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值