对象
定义
- 无序的数据集合
- 键值对的集合
- 拥有属性和方法的数据
- 可以说对象是变量的容器
写法
let obj = { 'name': 'frank', 'age': 18}
let obj = new Object({'name': 'frank'})
console.log({'name': 'frank', 'age': 18})
细节
- 键名是字符串,不是标识符,可以包含任意字符
- 引号可以省略,省略之后,省略之后就只能写标识符
- 就算引号省略了,键名也还是字符串
- 要用变量的值用[]把键名括起来
- 属性名:每个key都是对象的属性名
- 属性值:每个value都是对象的属性值
- 所有属性名会自动变成字符串
变量做属性名
- 之前都是用常量做属性名
- let p1 = 'name'
- let obj = {p1:'frank'},这样写,属性名为'p1'
- let obj = {[p1]:'frank'},这样写,属性名为name
- 不加 []的属性名会自动变成字符串
- 加了[]则会变成变量求值
- 值如果不是字符串,则会自动变成字符串
- 除了字符串,symbol也能做属性名
对象的隐藏属性
- JS中每一个对象都有一个隐藏属性
- 这个隐藏属性储存着共有属性组成的对象的地址
- 这个共有属性组成的对象叫做原型
增删改查
删除属性
- delete obj.xxx或 delete obj['xxx'] :即可删除obj的xxx属性,属性名和属性值同时删除
- obj.xxx = undefined只会删除属性值,不会删除属性名
- 含有属性名,但是值为undefined: 'xxx' in obj && obj.xxx === undefined
- 'xxx' in obj 如果为true表示还在 false表示删除
读属性
- console.dir(xxx)以目录的形式打印出来所有属性可以查看共有属性
- Object.keys(xxx)查看所有键名
- Object.values(xxx)查看所有值
- Object.entries(xxx)查看所有属性名和值
- 判断一个属性是自己的还是共有的:obj.hasOwnProperty('toString')
- 查看属性:
- 中括号语法: obj['key']
- 点语法: obj.key
- 读的时候可以访问原型
原型
- 每个对象都有原型
- 原型里面所有的属性都是共有的
- 对象的原型也是对象,
- 共有属性的原型现在被人为指定为null
- obj = {}为所有对象的原型,这个原型包含所有对象的共有属性,是对象的根
修改或增加属性(写属性)
- Object.assign(obj,{age:18,gender:'man'}) 批量赋值
- let obj = {name = 'frank'}
- obj.name = 'frank',这里的name是字符串
- obj[name]这里的name是变量
- obj['name'] = 'frank'
- obj['na'+'me'] = 'frank'
- let key = 'name'; obj[key] = 'frank'
- 无法通过自身修改或增加共有属性
- 要修改原型 window.Object.prototype.toString = 'xxx',一般不要修改原型
- 修改隐藏属性:
- let obj = Object.create(common)
- obj.name = 'frank'
new X()自动做四件事情
- 自动创建新对象、
- 自动为空对象关联原型,原型地址指定为X.prototype
- 自动将空对象作为this关键字运行构造函数
- 自动return this
- new后面的函数,使用名词形式
- 如new Person()
- 其他函数一般使用动词开头
- createSquare(5)
构造函数X
- 用来构造对象的函数叫做构造函数
- X函数本身负责给对象本身添加属性
- X.prototype对象负责保存对象的共用属性
- 所有构造函数首字母大写
- 所有被构造出来的对象,首字母小写
JS里面唯一的公式
如何确定一个对象的原型?
你是谁构造的你的原型就是谁的prototyp)属性对应的对象
原型公式:对象.proto_ === 其构造函数.prototype
对象分类
Object创建出来的对象是最没有特色的
类型 VS 类
- 类型是JS数据的分类,一共有7种,四基两空一对象
- 类 是针对于对象的分类有无数种,常见的有Array、Function、Date等
数组对象
定义一个数组
- let arr = [1,2,3]
- let arr = new Array(1,2,3) //元素为1,2,3
- let arr = new Array(3) //长度为3
数组对象的自身属性
- '0', '1', '2', '3', 'length' 属性名都是字符串
数组对象的共用属性
- shift 删除数组第一个元素,返回数组的长度
函数对象
定义一个函数
- function fn(x,y){return x+y}
- let fn = new Function('x','y','return x+y')
函数对象的自身属性
- name,length
共有属性
- apply/call/bind/
- window的构造者是Window
- window.Object是由window.Function构造出来的
- 所有的函数都是window.Function构造出来的
- window.Function是由window.Function构造出来的
JS数组
JS其实没有真正的数组,只是用对象模拟数组
JS的数组不是典型的数组
典型的数组
- 元素的数据类型相同
- 连续的内存存储
- 通过数字下表获取元素
JS的数组
- 元素的数据类型可以不同
- 内存不一定是连续的(对象是随机存储的)
- 不能通过数字下标
- 意味着数组可以有任何的key
创建一个数组
新建
- let arr = [1,2,3]
- let arr = new Array(1,2,3)
转化
- let arr = '1,2,3'.split(;)
- let arr = '123'.split('')
- Array.from('123')这个对象有0123下标有length属性才可以变成数组
伪数组
- let divList = document.querySelectorAll('div')再用Array.from使其变成数组
- 伪数组的原型链中没有数组的原型
合并数组
- arr3.concat(arr4) 创建一个新数组,之前的不变
- arr5.slice(2),从第三个位置开始切断之前的没有创建新的数组之前的不变
- 可以使用slice(0)复制一个数组
- JS只提供浅拷贝
删元素
跟对象一样
- let arr = ['a','b','c']
- delete arr[0]
- arr //[empty,'b','c']
- 删除元素之后,数组长度不变
- 稀疏数组
直接修改length可以删除元素
- arr.length = 2
- 会删除第二个元素之后的元素
删除头部的元素
- arr.shift()
- arr被修改,并返回被删元素
删除尾部的元素
- arr.pop() //arr被修改,并返回被删元素
删除中间元素
- arr.splice(index,1)//删除index位置的元素
- arr.splice(index,1,'x')//并在删除位置添加'x'
- arr.splice(index,1,'x','y')//并在删除位置添加'x''y'
- arr.splice(index,number)//index指从第几个开始删除,number指从该位置起删除几个
- 一个对象提供的函数就叫API
查看所有元素
查看所有属性名
- let arr = [1,2,3,4,5]
- Object.keys(arr)
for循环访问
for(let i = 0; i < arr.length; i++){
console.log(`${i}: ${arr[i]`)
}
forEach
arr.forEach(function(item,index){console,log(`${index}: ${item}`)})
区别是上面:for里面有break,continue但forEach不支持,for循环是关键字不是函数,是块
查看单个属性
- arr[0]
索引越界
- arr[arr.length] === undefined
- arr[-1] === undefined
元素是否在这个数组中
- arr.indexOf(item) 不是-1就证明存在
使用条件查找元素
- arr.find(function(x){ return x%2 === 0})
- arr.findOf(item => item&2 ===0)
使用条件查找元素的索引
- arr.findIndex(item => item%2 ===0) //找第一个偶数索引
增加数组中的元素
在尾部加元素
- arr.push(newItem) //修改arr,并返回新长度
- arr.push(item1,item2)
在头部加元素
- arr.unshift(newItem)
- arr.unshift(item1,item2)
在中间添加元素
- arr.splice(index,0,'x')
- arr.splice(index,0,'x','y')
反转顺序
- arr.reverse() //修改原来的数组为反转数组
- 反转字符串
let s = 'abcde'
s.splite('')
s.splite('').reverse()
s.splite('').reverse().join('')
// "ebcda"
排序
- arr.sort() //变成从小到大
- 自定义顺序: arr.sort((a,b) => a-b)
数组变换
map
- n变n
- arr.map(item => item*item)
filter
- n变少
- arr.filter(item => item %2 ===0 ? ture : false)
- arr.filter(item => item %2 ===0 ) //上下等价
reduce
- n变1
- arr.reduce((sum, item) => { return sum+item } , 0) //return的值作为下一次的初始值