一个基本数据类型当你使用的时候会自动转换成复杂数据类型,当你使用完毕,会自动转换为基本数据类型
比如 字符串 string是基本数据类型,但是它可以使用 length这个方法 ,就是因为字符串也是一个包装数据类型,当使用 legnth方法时,会自动转化为复杂数据类型,当使用完毕后,会自动转换为基本数据类型就像 对象 可以使用 点语法一样, 因为对象本身就是一个复杂数据类型所以可以使用
const obj = {}
// 因为obj 是一个对象 ,也就是一个复杂数据类型 可以使用 点语法
obj.name = 'hello world'
const str = 'hello world'
// str 是一个基本数据类型 可以使用 点语法 是因为 它也是一个包装数据类型
str.length
可以将一个数字类型转换为字符串类型
也可以进行进制转换
const num = 100
console.log(num.toString()) // 100
console.log(num.toString(2)) // 1100100
保留小数点
const num = 12
console.log(num.toFixed(2)) // 12.00
括号里面填写你要转换的数据,会把你要转换的内容一位一位的看,如果第一位就不能转换成数字,那么直接给NaN,如果第一位可以,就看第二位,第一位保留,以此类推
parseInt(10.11) // 10
parseInt("10.11") // 10
### parseFloat()
和parseInt的解析规则一模一样,只不过parseFloat认识小数点
* 可以传入number类型 和 string类型
```js
parseFloat(10.11) // 10.11
parseFloat("10.11") // 10.11
var random =Math.floor(Math.random()*(max-min+1))+min
我的理解是:JavaScript中一个函数,如果访问了外层作用域的变量,那它就是一个闭包
闭包的作用:
定义在函数内部的变量就是私有变量
利用闭包函数访问
闭包的特点:
优点:不会污染全局
缺点:外部不能访问,需要闭包函数
优点:不局限于私有变量
缺点:外部访问需要闭包
最大的缺点:一个不会被销毁的函数空间 (内存泄漏)
语法:
Object.defineProperty(obj, prop, descriptor)
obj
要定义属性的对象。
prop
要定义或修改的属性的名称或 Symbol 。
descriptor
要定义或修改的属性描述符。
语法:
Object.defineProperties(obj, props)
obj
在其上定义或修改属性的对象。
props
要定义其可枚举属性或修改的属性描述符的对象。对象中存在的属性描述符主要有两种:数据描述符和访问器描述符。
获取对象原型语法:
对象.__proto__
Object.getPrototypeOf(对象)
原型的作用:
当我们通过[[get]] 方式去获取一个属性对应的value时,它会优先在自己的对象中查找,如果找到直接返回,没有就会去这个对象的原型查找,这一个过程被称作原型链
函数天生自带一个显示原型 prototype属性,只要是一个函数都有
函数也属于对象,所以函数也有隐式原型对象 __proto__
const str = "World"
const str2 = `Hello ${str}` // Hello World
还可以调用函数
function foo(name, age, ...arg) {
console.log(name) // abc def
console.log(age) // 123
console.log(arg) // 456
}
foo`abc${123}def${456}`
函数的默认参数
function foo(a = 10, b = 20) {
console.log(a) // 10
console.log(b) // 20
}
foo()
展开语法是一个浅拷贝
数组:
const arr = [10, 20, 30, 40, 50]
const newArr = [...arr]
console.log(newArr)
创建对象字面量
const infos = {
age: 20
}
const obj = {
...infos,
name: "code"
}
Symbol是基本数据类型,表示独一无二的的值
const username = Symbol()
const username2 = Symbol()
const obj = {
[username]: "code",
[username2]: "code2"
}
console.log(Object.getOwnPropertySymbols(obj))
set和map是ES6新增的一种数据结构
解决的痛点:
由于JavaScript对象的key只能是字符串,所以新增了set和map,set和map可以让对象的key是多种类型,而不是单单限制为string类型,也就是说set和map让对象的key可以是任意类型。
Set是新增的数据结构,可以用来保存数据,类似于数组,但是和数组的区别是元素不能重复
创建Set我们需要通过Set构造函数(暂时没有字面量创建方式)
可以存储任意类型的唯一值,set里面的元素不会重复
和set数据结构相似
区别:
WeakSet中只能存储对象类型,不能存放基本数据类型
WeakSet对元素的引用是弱引用,如果没有其他引用对某个对象进行引用,那么GC可以对该对象进行回收
:::
这也意味着 WeakSet 中没有存储当前对象的列表。正因为这样,WeakSet 是不可枚举的。
:::
映射的意思,表示键到值的映射,Map保存的是键值对
语法:
new Map()
实例化的时候里面接受一个二维数组
里层数组的[0]作为key
里层数组的[1]作为value
const m = new Map([ ["name","xiaoluo"] ])
Map常见属性:size:返回Map中元素的个数
Map常见的方法
const map = new Map()
map.set("age",18)
// 也可以设置复杂数据类型为key
map.set([1, 2, 3],[4, 5, 6])
console.log(map)
![image](https://img-blog.csdnimg.cn/img_convert/6a5e2bf67db840417689c44fe5043514.png)
2. get(key):根据key获取Map中的value
```js
console.log(map.get("age")) //18
has(key):判断是否包括某个key,返回Boolean类型
delete(key):根据key删除一个键值对,返回Boolean类型
clear():清空所有的元素
forEach()可以遍历Map
js面试题
const obj = {}
let a = { name: 'Jack' }
let b = { age: 18 }
obj[a] = 100
obj[b] = 200
console.log(obj[a]) // 200
console.log(obj[b]) // 200
因为对象的key只能存储字符串,当把不是一个字符串的内容当作对象的key来使用,会自动转化为字符串 ,也就是
[object object]
const obj = {}
let a = { name: 'Jack' }
let b = { age: 18 }
// 由于a是一个对象类型 ,不是字符串,所以会自动转换成 [object object],
// 所以 a 是[object object],b也是[object object] 两个是一样的
obj[a] = 100
obj[b] = 200
console.log(obj[a]) // 200
console.log(obj[b]) // 200
const obj = {
name: " study",
age: 19,
height: 1.99,
address: "广州市"
}
console.log(Object.keys(obj))
console.log(Object.values(obj))
const entries = Object.entries(obj)
for (let item of entries) {
const [key, value] = item
console.log(key, value)
}
Object.entries() 对象转数组
flat :
const arr = [10, [20, 30], 40, [30, 40, 1, [20, 30]], 40, 50]
console.log(arr.flat(Infinity));
flatMap : 先进行 map 方法 在进行 flat
formEntries:数组转对象
对象的属性,而Proxy监听的是对象本身
使用Object.definProperty需要遍历对象的每个属性,而Proxy则直接代理对象,不需要遍历操作
Proxy对新增属性也可以监听,Object.defineProperty不可以(只能对设置和访问监听)
Proxy可以监听数组和函数的变化
const p1 = new Proxy(target,handler)
set有四个参数:
target:目标对象(侦听的对象)
property:将被设置的属性 key
value:新的属性值
receiver:调用的代理对象
get有三个参数
target:目标对象(侦听的对象)
property:被捕获的属性key
receiver:调用的代理对象
const obj = {
username: "code",
age: 20,
address: "重庆"
}
const p1 = new Proxy(obj, {
set(target, property, value, receiver) {
target[property] = value
},
get(target, property, receiver) {
return target[property]
}
})
handler.deleteProperty() 方法用于拦截对对象属性的 delete 操作
语法:
var p = new Proxy(target, {
deleteProperty: function(target, property) {
}
});
deleteProperty有两个参数:
target:目标对象
propety:待删除的属性名
const obj = {
username: "code",
age: 20,
address: "重庆"
}
const p1 = new Proxy(obj, {
set(target, property, value, receiver) {
target[property] = value
},
get(target, property, receiver) {
return target[property]
},
deleteProperty(target, property) {
console.log("删除成功")
delete target[property]
}
})
Reflect (反映) 是一个内置的对象,它提供拦截 JavaScript 操作的方法。这些方法与 proxy handler (en-US) 的方法相同。Reflect 不是一个函数对象,因此它是不可构造的。
Reflect 的所有属性和方法都是静态的(就像 Math 对象)。
const obj = {
name: 'why',
age: 18
}
const objProxy = new Proxy(obj, {
set(target, prop, newvalue, receiver) {
const isSuccess = Reflect.set(target, prop, newvalue, receiver)
if (isSuccess) {
console.log(prop, "修改成功")
} else {
console.log(prop, "修改失败")
}
},
get(target, props, receiver) {
return target[props]
}
})
objProxy.name = 'kobe'
console.log(objProxy)
RegExp (Regular Expression)
专门用来验证字符串是否符合规则
从字符串里面获取一部分符合规则的内容
:::
const reg = /abcd/
:::
:::
const reg = new RegExp(“abcd”)
:::
语法:正则.test(你要检测的字符串)
const reg = /abc/
console.log(reg.test("abc123")) // true
语法:正则.exec(“字符串”)
const reg = /abc/
console.log(reg.exec("abc"))
组成正则的基本符号
\s 表示一个空格
\S 表示一个非空格
\t 表示一个制表符
\d 表示一个数字
\D 表示一个非数字
\w 表示需要一个数字或字母或者下划线
\W 表示除了一个数字或字母或者下划线 以外的字符
. 点 表示非换行
^ 表示字符串开始
$ 表示字符串结束
写在普通元字符或者字母符号的后面
修饰前面一个符号的出现次数
* 星号 表示出现 0 —— 多次
? 问号 表示出现0 —— 1 次
{n} 指定出现 n 次
{n,} 指定出现 n 到多次
{n,m} 指定出现 n 到 m 次
在限定符后面加上?就是非贪婪
() 表示一个整体
| 表示左边或者右边的都行
[]表示符合里面的一个就行
[^] 非里面的任意一个就行
- 中划线 使用在 [] 里面的一个符号 表示 从 那 到 那
特殊说明:当点出现在 [] 或者 [^] 里面的时候 表示一个 点文本
标识符是写在正则表达式的外面
i 作用:忽略大小写
g 作用:全局
y 作用:粘性全局
宏任务开始到宏任务结束
宏任务是一次执行一个,微任务是到微任务就把微任务里面的所有执行完,才到宏任务