原始(Primitive)类型
- boolean
- null
- undefined
- number
- Infinity(无穷大
- NaN(非数字
- string
- symbol
首先原始类型存储的都是值,是没有函数可以调用的
对象(Object)类型
- JS 中,除了原始类型那么其他的都是对象类型了
- 对象类型和原始类型不同的是,原始类型存储的是值,对象类型存储的是地址(指针)
数组
-
push pop shift(删除数组第一个元素 并返回删除的元素) unshift(将一个或者多个元素添加到数组开头) splice(删除数组中指定元素) 在原数组基础上修改
-
concat 合并数组 返回一个新数组
-
slice 取原数组中的某几项 返回一个新数组
-
filter 过滤操作,筛选符合条件的所有元素,若为true则返回组成新数组
-
map 映射操作,对原数组每个元素进行处理,并回传新的数组
-
reduce 归并操作,总共两个参数,第一个是函数,可以理解为累加器,遍历数组累加回传的返回值,第二个是初始数值。如果没有提供初始值,则将使用数组中的第一个元素
-
from 将类似数组的对象 和 可遍历对象 转为真正的数组
let arrayLike = { '0': 'a', '1': 'b', '2': 'c', length: 3 }; let arr2 = Array.from(arrayLike); // ['a', 'b', 'c'] // 对象必须有 length 属性 Array.from(arrayLike).map(x => x * x); // 等价于 Array.from(arrayLike, x => x * x)
-
of 将一组值转为数组 (主要目的是弥补数组构造函数 Array() 的不足
- Array(3) // [ , , ]
- 当参数只有一个 返回制定数组长度
-
find 找出第一个符合条件的数组成员
可以接受三个参数 依次为当前的值 当前的位置 原数组
参数是一个回调函数 对所有数组成员依次执行该回调函数 直到找出第一个返回值为 true 的成员 返回该成员
如果没有符合条件的成员 则返回 undefined[1, 4, -5, -10].find(n => n<0) [1, 5, 10, 15 ].find((value, index , arr) => { return value > 9; })
-
findIndex 同 find 用法非常类似 返回第一个符合条件数组成员位置 若均不符合 则返回 -1
-
fill 使用给定的值 填充数组 数组已有元素 会被抹去
第二个 第三个 用于指定 起始位置 结束位置['a', 'b', 'c'].fill(7) // [7, 7, 7] ['a', 'b', 'c'].fill(7, 1, 2) // ['a', 7 , 'c']
-
includes() 返回布尔值 表示数组是否包含给定值
[1, 2, 3].includes(2) // true
字符串
判断字符串是否包含在另一个字符串中
-
includes() 返回布尔值 表示是否找到参数字符串
-
startsWith() 返回布尔值 字面意思
-
endsWith() 返回布尔值 字面意思
-
repeat()
-
padStart() padEnd()
- 补全字符串
'x'.padStart(5, 'ab') //ababx
'x'.padEnd(4, 'ad') //xada
-
trim()
- 去除字符串 空格 和 换行符
-
raw()
- 将字符串中的转译符号也当变量处理
函数
-
函数作用域 在调用时形成
-
arguments // 将参数转为一个类似数组的对象 仅有下标 length 属性 无pop等方法
-
允许设置参数默认值
function Point(x=0, y=0) {
}
- length
- 返回参数个数( 不含确定默认值的 和 rest参数
- rest 参数
- 获取函数多余参数 将多余参数放入数组
- 扩展运算符 …
- 将一个数组转为用 , 分隔的参数序列
补充:
Typeof:
- typeof 运算符把类型信息当作字符串返回。typeof 返回值有六种可能: “number,” “string,” “boolean,” “object,” “function,” 和 "undefined."我们可以使用typeof来获取一个变量是否存在
比较大小
字符串 比较对应的字符编码大小
= = 和 = = =
== 和 != 比较若类型不同,先偿试转换类型,再作值比较,最后返回值比较结果
而
=== 和 ! = = 只有在相同类型下,才会比较其值
valueOf:
- valueOf方法由Object后面的每个对象继承。 每个内置的核心对象都会覆盖此方法以返回适当的值。如果对象没有原始值,则valueOf将返回对象本身
- 你很少需要自己调用valueOf方法;当遇到要预期的原始值的对象时,JavaScript会自动调用它
对象 | 返回值 |
---|---|
Array | 返回数组对象本身 |
Boolean | 布尔值 |
Date | 存储的时间是从 1970 年 1 月 1 日午夜开始计的毫秒数 UTC |
Function | 函数本身 |
Number | 数字值 |
Object | 对象本身 |
String | 字符串值 |
Math 和 Error 对象没有 valueOf 方法 |
toString( ):
- 返回对象的字符串表示
toString 与 valueOf
js {}+{}的结果 推荐1
js {}+{}的结果 推荐2
for … in … 与 for … of …
- 推荐在循环对象属性的时候,使用for…in,在遍历数组的时候的时候使用for…of。
- for…in循环出的是key,for…of循环出的是value
- 注意,for…of是ES6新引入的特性。修复了ES5引入的for…in的不足
- for…of不能循环普通的对象,需要通过和Object.keys()搭配使用
- for…of循环不会循环对象的key,只会循环出数组的value,因此for…of不能循环遍历普通对象,对普通对象的属性遍历推荐使用for…in (如果实在想用for…of来遍历普通对象的属性的话,可以通过和Object.keys()搭配使用,先获取对象的所有key的数组
然后遍历
in关键字用来检查对象中是否存在指定的属性(包含实例属性和原型属性)
对象的hasOwnProperty方法用来检查对象中是否存在指定的属性(只检查实例属性)
函数参数是对象
function test(person) {
person.age = 26
person = {
name: 'yyy',
age: 30
}
return person
}
const p1 = {
name: 'yck',
age: 25
}
const p2 = test(p1)
console.log(p1) // -> ?
console.log(p2) // -> ?
- 首先,函数传参是传递对象指针的副本
- 到函数内部修改参数的属性这步,我相信大家都知道,当前 p1 的值也被修改了
- 但是当我们重新为 person 分配了一个对象
- 最后 person 拥有了一个新的地址(指针),也就和 p1 没有任何关系了,导致了最终两个变量的值是不相同的( p1 并没有被销毁 )
类型转换
let a = {
valueOf() {
return 0
},
toString() {
return '1'
},
[Symbol.toPrimitive]() {
return 2
}
}
- 对象转原始类型
- Symbol.toPrimitive > valueOf > toString
- 当做 + 时 如果 valueOf 得不到原始值 会调用 toString
- 只有 + 会将后面强制转换为数字
this
function foo() {
console.log(this)
console.log(this.a)
}
var a = 1
foo()
const obj = {
a: 2,
foo: foo
}
obj.foo()
const c = new foo()
对于直接调用 foo 来说,不管 foo 函数被放在了什么地方,this 一定是 window
对于 obj.foo() 来说,我们只需要记住,谁调用了函数,谁就是 this,所以在这个场景下 foo 函数中的 this 就是 obj 对象
对于 new 的方式来说,this 被永远绑定在了 c 上面,不会被任何方式改变 this
function a() {
return () => {
return () => {
console.log(this)
}
}
}
console.log(a()()())
首先箭头函数其实是没有 this 的,箭头函数中的 this 只取决包裹箭头函数的第一个普通函数的 this
另外对箭头函数使用 bind 这类函数是无效的
不管我们给函数 bind 几次,fn 中的 this 永远由第一次 bind 决定,所以结果永远是 window
== VS ===
==
- ==
- 来说,如果对比双方的类型不一样的话,就会进行类型转换
- ===
- 就是判断两者类型和值是否相同
[] == ![] // true
!![] == true // true
[] == false // true
深拷贝 浅拷贝
首先深复制和浅复制只针对像 Object, Array 这样的复杂对象的。简单来说,浅复制只复制一层对象的属性,而深复制则递归复制了所有层级
// 浅拷贝
let a = {
age: 1
}
let b = { ...a }
a.age = 2
console.log(b.age) // 1
// 深拷贝
function deepClone(obj) {
function isObject(o) {
return (typeof o === 'object' || typeof o === 'function') && o !== null
}
if (!isObject(obj)) {
throw new Error('非对象')
}
let isArray = Array.isArray(obj)
let newObj = isArray ? [...obj] : { ...obj }
Reflect.ownKeys(newObj).forEach(key => {
newObj[key] = isObject(obj[key]) ? deepClone(obj[key]) : obj[key]
})
return newObj
}
let obj = {
a: [1, 2, 3],
b: {
c: 2,
d: 3
}
}
let newObj = deepClone(obj)
newObj.b.c = 1
console.log(obj.b.c) // 2