- Object类型
- Array类型
- 检测数组的方法:
- 转换方法:
- ES5:
- 所有对象都有toLocaleString()、toString()和valueOf()方法。其中,调用valueOf()返回的还是数组本身,调用数组的toString()方法会返回由数组中每个值得字符串形式拼接而成的一个以逗号分开的字符串。实际上,为了创建这个字符串会调用数组的每一项的toString()方法。
- ES6:1. Array.from()
- 方法将用于将两类对象转为真正的数组:类似数组的对象(array-like object)和可遍历对象(iterable)的对象(在这里包括Set和Map)。下面是一个类似数组的对象,Array.from将它转换为真正的数组:
- 2. Array.of()将一组值转换为数组:这个方法的目的是为了弥补数组构造函数Array()的不足
- 栈方法
- 队列方法:
- 重排序方法
- 迭代方法:es5:
- es6:
- 归并方法:
- Date()类型
- RegExp()类型
- Function()类型
- 基本包装类型
- 单体内置对象
Object类型
Object.prototype == Function.prototype.__proto__//true
//内部实现了 Function.prototype = new Object()
//申明对象时要注意这个小点:
var perosn = {} //这样申明是与 new Object()相同的
向函数传递大量可选参数时,可以使用对象字面量申明的方式实现,例如:
function displayInfo(args){
var output = ""
if(typeof args.name == "string"){
output += "Name:" + args.name + "\n"
}
if(typeof args.age == "number"){
output += "Age:" + args.age + "\n"
}
console.log(output)
}
displayInfo({
name:"pp",
age:24
})
//Name:pp
//Age:24
Array类型
在ECMAScript的数组中,它和其他语言不同,数组中的元素可以不需要申明它是什么类型的数组,字符串,数字都可以直接添加进数组中。
它的 length
属性不是只读的,是可以修改的:
var colors = [1,2,3]
colors.length = 2
console.log(colors[2])//undefined
数组可以这样加一个值喔:
var arr = [1,2,3]
arr[arr.length] = 4
console.log(arr)//[1,2,3,4]
检测数组的方法:
- value instanceof Array
- ES5增加的Array.isArray()方法:
用法:
if(Array.isArray(value)){
//对数组执行某些操作
}
//isArray()的实现原理
function isArray(value){
return (Object.prototype.toString.call(value) == "[object Array]")
}
转换方法:
ES5:
所有对象都有toLocaleString()、toString()和valueOf()方法。其中,调用valueOf()返回的还是数组本身,调用数组的toString()方法会返回由数组中每个值得字符串形式拼接而成的一个以逗号分开的字符串。实际上,为了创建这个字符串会调用数组的每一项的toString()方法。
var color = ["red","blue","green"]
color.toString()//"red,blue,green"
color.valueOf()// ["red", "blue", "green"]
ES6:1. Array.from()
方法将用于将两类对象转为真正的数组:类似数组的对象(array-like object)和可遍历对象(iterable)的对象(在这里包括Set和Map)。下面是一个类似数组的对象,Array.from将它转换为真正的数组:
let arrayLike = {
'0':'a',
'1':'b',
'2':'c',
length:3
}
//es5:
var arr1 = [].slice.call(arrayLike)//["a","b","c"]
//es6:
let arr2 = Array.from(arrayLike)//["a", "b", "c"]
实际应用中,常见的类似数组的对象是DOM操作返回的NodeList集合,以及函数内部的arguments对象。 Array.from
都可以将它们转换为真正的数组。
//NodeList对象
let ps = document.querySelectorAll('p')
Array.from(ps).filter(p => {return p.textContent.length > 100})
//arguments对象
function foo(){
var args = Array.from(arguments)
}
Array.from()的可以将任何值转换为数组,它的第二个参数是一个函数,还会实现map的功能。
它的一个用处是将字符串转换为数组,再返回字符串的长度
function countSymblos(string){
return Array.from(string).length
}
countSymbols("我要减肥")
//4它可以正确返回中文字符串的长度(大于 \uFFFF 的unicode字符串)
2. Array.of()将一组值转换为数组:这个方法的目的是为了弥补数组构造函数Array()的不足
Array(3)//[, , ,]
Array.of(3,11,8)//[3,11,8]
Array.of(1)//[1]
//模拟实现Array.of()
function Arrayof(){
return [].slice.call(arguments)
}
栈方法
数组可以表示成栈。栈是一种后进先出的数据结构,它值发生在栈的顶部位置。而ECMAScript为数组专门提供了 push()
和 pop()
方法,以便实现类似的行为。
var colors = new Array()
var count = colors.push("red","green")//push()方法向数组尾部添加元素,并返回修改后的数组长度
count//2
count = colors.push("black")
count//3
var item = colors.pop()//pop()方法从数组尾部取出值来,然后返回移除的值
item//"black"
队列方法:
数组也可以表示队列(队列:先进先出),ECMAScript为数组专门提供了push()方法和shift()方法来实现。
shift()方法是取出头部的元素
var colors = new Array()
var count = colors.push("red","blue")
count//2
count = colors.push("black")
count//3
var item = colors.shift()//"red"
colors.length//2
unshift()
方法和 pop()
方法可以实现相反的队列,从头部添加元素,从尾部弹出元素。
重排序方法
数组中已经存在两个可以直接用来排序的方法: reverse()
和 sort()
。他们的返回值都是排序后的数组
迭代方法:es5:
- every():对数组中的每一项运行给定函数,如果该函数对每一项都返回
true
,则返回true
; - filter():对数组中的每一项运行给定函数,返回该函数会返回true的项组成的数组
- forEach():对数组的每一项运行给定函数。这个方法没有返回值。(该方法本质上就是对数组进行了for循环哈哈哈)
- map():对数组中的每一项运行给定函数。返回每次函数调用的结果组成的数组。
- some():对数组中的每一项运行给定函数,如果该函数的任意一项返回true,则返回true
(以上这些方法都不会修改数组中包含的值)
var numbers = [1,2,3,4,5]
var everyResult = numbers.every(function(item,index,array){
return (item > 2)
})
console.log(everyResult)//false
var numbers = [1,2,3,4,5]
var someResult = numbers.aome(function(item,index,array){
return (item > 2)
})
console.log(someResult)//true
filiter():
var numbers = [1,2,3,4,5]
var filterResult = numbers.filter(function(item,index,array){
return (item > 2)
})
console.log(filterResult)//[3, 4, 5]
numbers//numbers没有改变
//(5) [1, 2, 3, 4, 5]
map():
var numbers = [1,2,3,4,5]
var mapResult = numbers.map(function(item,index,array){
return item*2
})
console.log(mapResult)//[2,4,6,8,10]
es6:
find()
方法:用于找出第一个符合条件的数组元素。它的参数是一个回调函数,所有数组成员依次执行该回调函数,直到找出第一个返回值为true
的成员,然后返回该成员。如果没有符合条件的成员,则返回undefined
。
[1,4,-5,10].find((n) => n < 0)
//-5
//find中的参数的回调函数接受三个参数,当前的值,当前的索引和当前的函数
[1,5,10,15].find(function(value,index,array){
return value > 9
})//10
findIndex()
方法:与上面的方法类似,不同的是当没有值返回true时,它会返回-1
function f(v){
return v > this.age
}
let person = {name:'pp',age:24}
[10,12,26,15].find(f,person)//26
两个方法都可以识别NaN,弥补了indexOf()的不足
[NaN].findIndex(y => Object.is(NaN,y))//0
归并方法:
ES5:reduce()
和 reduceRight()
。这两个方法都会迭代数组所有的项,然后构建一个最终返回的值。
这两个方法都会迭代数组所有的项,然后构建一个最终返回的值。其中, reduce()
方法从数组的第一项开始,逐个遍历到最后。而 reduceRight()
则从数组的最后一项开始,向前遍历到第一项。
var values = [1,2,3,4,5]
//reduce可以接受两个参数,一个参数是一个在每一项上都会调用的函数和作为归并基础的初始值(第二个参数可选)。
//调用函数有四个参数(pre:前一个值,cur:当前值,index:当前值的索引,array:数组对象)
var sum = values.reduce(function(prev,cur,index,array){
return prev + cur
})
console.log(sum)
Date()类型
RegExp()类型
Function()类型
每个函数都是 Function
类型的实例,而且都与其他引用类型一样具有属性和方法。由于函数是对象,因此函数名实际上也是一个指向对象的指针,不会与某个函数绑定。函数通常是使用函数申明语法定义的,如下面的例子:
```
function sum(num1,num2){
return num1 + num2
}
var sum = function(num1,num2){
return num1 + num2
}
函数没有重载:连续申明一个函数两次,第二次总会覆盖第一次。
解析器会先读取函数申明:也就是 function f(){}
的形式,然后才会读其他的形式,比如函数表达式 var f = function (){}
的形式,所以一般用函数表达式就不存在函数申明提升而造成的错误。
函数内部属性:
在函数内部有两个特殊的对象:arguments
和 this
。其中,arguments在第三章曾经介绍过,它是一个类数组对象(可以通过 Array.from``(likeArray)
转或者 [].slice.call(likeArray)
),包含着传入函数中的所有参数。虽然 arguments
的主要用途是保存函数参宿,但这个对象还有一个名为 callee
的属性,该属性是一个指针,指向拥有这个 arguments
对象的函数。请看下面这个灰常经典的阶乘函数。
function factorial(num){
if(num <= 1){
return 1
}else{
return num*factorial(num-1)
}
}
使用callee属性可以避免与factorial函数的过度耦合。
function factorial(num){
if(num <= 1){
return 1
}else{
return num*arguments.callee(num-1)//callee属性时指向函数factorial
}
}
this
函数内部的另一个特殊对象是 this
。this引用的是函数执行的环境对象——或者也可以说是this值(当在网页的全局作用域中调用函数时,this对象的引用就是 window
)。
this在函数调用之前都不知道它该指向谁。
window.color = "red"
var o = {
color:"blue"
}
function sayColor(){
console.log(this.color)
}
sayColor()//"red" 在调用函数之前this都无法确定它该指向谁,谁在调用它,它才指向谁
o.sayColor = sayColor//给对象o一个新方法sayColor,并将sayColor赋给它。
o.sayColor()//"blue"//这时调用sayColor,this就指向了o
函数的属性和方法
函数的属性:
- length:代表参数的个数哈哈哈。
- prototype:这个属性是ECMAScript中的引用类型保存所有实例方法的真正所在。比如toString()。valueOf()等方法实际上都保存在prototype名下。
函数的方法:
- apply():在指定的作用域中调用函数。实际上在设置函数体内this对象的值。首先,apply()方法接受两个参数:一个是在其中运行函数的作用域,另一个是参数数组。
- call():在指定的作用域中调用函数。call 的作用和apply是相同的,但是不同的是它接受参数的形式和apply是不同的,它接受的参数要逐个列举出来,而不是一个参数数列。
function sum(num1,num2){
return num1 + num2
}
function callSum1(num1,num2){
return sum.apply(this,arguments)//传入arguments对象
}
//上面这段代码就相当于下面这段啦
callSum1(10,10)
function sum(num1,num2){
return num1+num2
}
function callSum1(num1,num2){
return sum(num1,num2)
}
callSum1(10,10)
es5的定义的方法 bind()
它返回的是一个函数哈哈,可以用到它的时候再调用。
基本包装类型
为了便于操作基本类型值,ECMAScript还提供了3个特殊的引用类型:Boolean,Number和String。这些类型与本章介绍的其他引用类型相似,但是同时也具有与各自的基本类型相应的特殊行为。实际上,每当读取一个基本类型值的时候,后台就会创建一个对应的基本包装类型的对象,从而让我们能够调用一些方法来操作这些数据。
var s1 = "some text"
var s2 = s1.substring(2)//从第二个子串开始的所有
//substring(from,to)//from是你想取的子字符串的开始位置,to是你想取的子字符串的结束位置,但是取得时候是
//左开右闭的
s2//"me text"
s2.substring(1,2)//"e"
这个例子中的变量s1包含了一个字符串,字符串当然是基本类型值。而下一行调用了s1的substring()方法,并将返回的结果保存在了s2中。我们知道,基本类型不是对象,因而他们应该是不能有方法的。其实,为了我们实现这种直观的操作,后台已经自动完成了一系列的处理。当第二行代码访问s1时,访问过程是处于一种读取模式,也就是要从内存中读取这个字符串的值。而在读取模式中访问字符串时,后台都会自动完成下列处理:
1. 创建String类型的一个实例
- 在实例上调用指定的方法
- 销毁这个实例
将以上代码想象是下面的步骤来处理上面那段代码(只是比喻,这里实际上不是这样):
var s1 = new String("some Text") //s1.__proto__ = String.prototype
var s2 = s1.substring(2)
s1 = null
所以这里的基本包装类型就和对象一样了,而且,上面着三个步骤也分别适用于Boolean和Number类型对于的布尔和数字值
引用类型和基本包装类型的区别主要在于他们的生命周期不同:引用类型在使用new操作符创建的引用类型的实例,在执行流离开当前作用域之前都一直保存在内存中。而自动创建的基本包装类型的对象,则只存在于一行代码的瞬间,然后立即就会被销毁,所以不能在运行时为基本类型值添加属性和方法。
var s = "ss"
s.color = "red"//为s添加新的属性,然后执行完这行,这个实例就销毁了
s.color//undefined//这时它又创建自己的String对象
Number
var num = 10.005
num.toFixed(2)//10.01 :toFixed()方法可以满足四舍五入
Boolean
string
单体内置对象
内置对象:由ECMAScript提供的、不依俩与宿主环境的对象,这样对象在ECMAScript程序之前就已经存在了。意思是说,开发人员不必显式的实例化内置对象。常见的内置对象为Objet,Array和String以及Global和Math
Global对象是“兜底对象”哈哈哈哈,它具有一些强大实用的方法
Global
URI编码方法
encodeURI()
和encodeURIComponent()
方法可以对URI进行编码,以便发送给浏览器。有效的URI中不能包含某些字符,他们使用特殊饿UTF-8编码替换所有无效的字符.
对应的解码为decodeURI()
和decodeURIComponent()
他两的区别如下:
var uri= "http://www.wrox.com/illegal value.htm#start"
//encodeURI()方法只替换空格
encodeURI(url)//"http:www.wrox.com/illeagl%20value.htm#start"
//encodeURIComponent()方法是使用对应的编码替换所有的非字母数字字符。
encodeURIComponent(url)//"http%3A%2F%2Fwww.wrow.com%2Fillegal%20value.htm%23start"
一般使用encodeURI()对整个URI,而只能对附加在现有URI后面的字符串使用encodeURIComponent()
eval()
eval()方法接受一个参数,既要执行的ECMAScript(javascript)字符串,就像一个解析器,不会存在变量提升或者函数提升,只有执行到eval()时才能执行其中的代码,比较容易受到代码注入攻击,不建议使用。
属性
Math对象
random()
方法返回大于等于0小于1的一个随机数。对于某些站点来说,这个方法非常好用
var num = Math.floor(Math.random()*sum+pre)//sum为数据总个数,pre为数据的第一个数,即可取到随机数