1.作用域:
分类:全局作用域,函数(局部)作用域【函数内可以形成局部作用域】,块级作用域【比如for循环】
全局作用域:
- 不在任何函数内定义的变量就具有全局作用域,默认全局对象window, 全局作用域的变量是window的一个属性。
- 顶层函数 的定义也被视为一个全局变量,并绑定到window 对象
js预解析,变量提升
变量与函数(均存放在栈内)的提升:
var a = 2
变量:实际是先在编一阶段声明(未初始化出现undefined),机器到执行阶段才会进行 初始化 赋值 ,故仅声明可被提升,
函数:声明优先提升,再调用。函数字面量不会被提升。
function foo(){
console.log('余光');
}
foo(); // 余光
foo(); //全局,not a function
foo = function(){//变量提升 undefined 非法应用TypeError
console.log('小李');
}
防止提升:const和let一样,只在声明所在的块级作用域内有效,也不会变量提升
作用域链,闭包:
- 概念:函数嵌套函数,内部函数就是闭包。
function outerFun() {
let a = 10;
function innerFun() { //innerFun就是闭包
console.log(a);
}
return innerFun;
}
let fun = outerFun();//接受闭包内部返回值
fun();//调用函数
- 由于函数存放在栈内,所以在函数外部无法调用函数内的变量。
而闭包:内部函数没有执行完成,外部函数不会被销毁, - 作用:闭包可以封装一段代码 ,实现模块化
- 应用:定义私有变量,外部访问返回值冒泡
let md = (function() {
let a = 10;
let b = 2;
function add() {
return a + b;
}
function sub() {
return a - b;
}
return {
add,
sub
}
})()
let m = md.add();
console.log(m);
this 指向
- 全局环境输出 this 指向 window(全局对象)
- 全局函数输出 this 指向 window(全局对象)的方法
- 对象的方法输出 this 指向 调用该方法的对象,
- DOM事件输出this 指向 DOM对象
- 构造函数(大写的函数名,用来创建对象)的this 指向
- new 关键字做了:将构造函数中的对象指向创造出来的对象
function F() {
this.name = "小明";
}
let f = new F() //new 将函数中的this 指向的f
- 箭头函数中的this指向: 箭头函数没有this属性,函数内普通定时器中this属性为window,而箭头函数指向函数内定时器外
call,apply,bind用法与区别:
call 是函数的方法,
- 可以调用函数,也可以改变函数中的this,
1. 调用函数
function fun() {
console.log("hello,world");
}
fun.call();
2. 改变函数中的this
let dog = {
name: "旺财",
food: "shit",
sayName(food1,food2) {
console.log(this.food1 + this.food2);
}
}
let cat = {
name: "喵喵"
}
dog.sayName.call(cat, "鱼","肉") //输出鱼,参数1:对象,参数2,形参
apply 和 call 区别:
call 参数列表依次往后,apply 需要 数组 传参
相同:允许直接调用
dog.sayName.apply(cat,["鱼"],["肉"])
bind , 传参和 call 传参一样,但会形成返回值,需要被调用
let fun = dog.sayName.bind(cat,"鱼","肉")
fun();
实际应用:实现多重继承
继承:子类使用父类方法
function Animal() {
//2. this指向cat1
this.eat = function() {
console.log("打印");
}
}
function Cat() {
//1. this指向cat1
Animal.call(this);
}
let cat1 = new Cat();
cat1.eat();
垃圾回收:标记清理
2.JS数据类型:原始类型与引用类型
总结
- 原始类型:Number,String,Boolen,Null,Undefined,symbol, bigint
- 引用类型:对象Object , Array,Data,Math
解析
原始类型:
-
string: 访问字符串单个字符: charAt(索引) ,索引下标法 s[0]
字符串转换:
String():适用于任何的数据类型(null -> null undefined -> undefined)
toString():null和undefined没有这个功能
console.log(null.toString()); //error 报错 -
Number:包含整数和浮点型(精度17位)
数值类型的转换:
Number():可以用于任何的数据类型
parseInt:提取 整数数值
paseFloat:提取浮点数值 -
NaN:非数字类型
判断是否是非数字型:- isNaN,返回true,false(传入的参数首先会被转化为数值,如果参数类型为对象类型,先调用valueOf()方法,再确定该方法返回的值是否可以转换为数值类型,如果不能,再调用toString()方法,再确定返回值)
- console.log(typeof 12) //Number
-
null ( 空对象指针类型 ): typeof返回 object 类型,表示尚未存在的对象
-
undedfined (申明了变量但是没有初始化,if语句中默认转化为false ) : 未被初始化,预定义的全局变量
典型的出现undefined情况
(1)变量被申明,等于undefined
(2)调用函数时,应该提供的参数没有提供,该参数等于undefined
(3)对象没有赋值的属性,该属性值为undefined
(4)函数没有返回值,默认返回undefined -
symbol: 新增数据类型,表示独一无二的值,定义对象唯一属性名
① symbol:新增表示唯一性,
用法:定义添加的属性名
不能通过 for…in 获取object.keys
let level = Symbol("level")
let student = {
name: "小明",
age: 12,
[level]: "优秀"
}
console.log(student);
for (let pro in student) {
console.log(pro);
//name , age,单独拿出来
}
//和下边相等
console.log(Object.keys(student));//放在数组里
拿到symbol值得方法:
Object.getOwnPropertySymbols 同样放在数组内
Symbol.iterator 【迭代器】是一个内置的值【是一个函数对象,返回一个拥有next方法的迭代器对象】 ,如果对象有该属性,可被for…of 【专门用来可迭代对象,对象本身默认是不可迭代的。运行时尝试对常规对象使用for/of会抛出TypeError】遍历 [ 数组有该属性 ]
-
bigint :
- 提供了对任意长度整数的支持。
- 创建 bigint 两种方式:
在一个整数字面量后面加 n
或者调用 BigInt 函数,该函数从字符串、数字等中生成 bigint。
let n1 = 123n
let n2 = 456n
let n3 = BigInt(789)
console.log(typeof n1) // bigint
console.log(n1+n2) // 579n
console.log(n2+n3) // 1245n
3 . number 和 bigint 属于不同类型,可能在进行 == 比较时相等,但在进行 ===(严格相等)比较时不相等
引用类型:
- 又称对象定义,描述对象的属性和方法
1. object: 方便存储和传输数据.
1)创建Object方法。new后O构造
var person = new Object();
person.name = "Alice";
person.age = 23;
person[5] = true;
2)字面量:
var person = {
"name" : "Alice",
age : 23, //当属性名是字符串时,引号(单、双引号)可用也可不用
5 : true
};
访问:点表示
alert(person.name);
方括号
alert(person["name"];
//属性名中包含空格等或属性名是数值时,不能用点表示法,只能用方括号表示法
alert(person["5"];
2.Array数组
-
判断是否是数组,
-
value instanceof Array
-
Array.isArray(value)
-
-
转换方法:
-
数字,数组,时间Data,正则表达式等,转化为字符串 a = 123; a.toString(2),数字转为对应数制字符串 [1,2,3].toString( ); 数组转化为字符串
-
valueOf(), 转为字符串
-
toLocaleString()
-
-
操作方法;
栈:入栈push(), 出栈pop()
队:入队push(),出队 shift()
重排序:array.sort(compare) 调用compare函数(内部a-b 升序,b-a降序)
连接数组:arr1.concat(arr2,arr3)
划分数组:arr.sllice(开始闭区,结束索引)
位置方法:arr.indexof()
迭代方法:1. 查询数组满足每一个条件:every
let arr = [1,2,3,4,5]
let a = arr.every(function(item,index)){
return (item > 5)
}
log(a) //false
2. 满足某些条件:some
let a = arr.some(function(item,index)){
return (item > 5)
}
log(a) //true
3.筛选符合条件项组成新数组 :filter
let arr = [1,2,3,4,5,6,7,8]
let a = arr.filter(function(item,index)){
return (item > 5)
}
log(a) //6,7,8
4.通过计算原数组的项组成新数组:map
let arr = [1,2,3,4,5,6,7,8]
let a = arr.map(function(item,index)){
return (item > 5)
}
log(a) //6,7,8
5. 传入数组每一项 forEach
let arr = [1,2,3,4,5,6]
let a = arr.forEach(function(item,index)){
log(item) //1,2,3,4,5,6
}
6.数据累加和:reduce
let arr = [1,2,3,4,5,6]
let a = arr.reduce(function(prev,cur,index)){
return prev + cur;
}
console.og(a);
3.Data类型
- 构造函数:
Date.now( );
Date.parse( );
Date.UTC( );
获取或设置:年,月,日,星期几,时,分,秒,毫秒
获取两个日期之间相隔的天数
计算两个日期之间相隔的天数
4.Math数学类型
获取最大值:Math.max(1,2,3,4)
获取最小值:Math.min(1,2,3,4)
向上舍入:Math.ceil(3.5) //4
向下舍入:Math.floor(3.7) //3
标准舍入;Math.round(3.2)
产生随机数:Math.random( )
等等
5.RegExp类型
正则表达式
提取字符串:arr.substring(开始,结束)
6.单体内置对象【待补】
字符串转为js代码: eval(string)
7.映射 Map
- 定义:由键值对构成,与对象区别:其键可是任何类型(可以是键),而对象只能使用字符串作为属性名称
- 常用方法:
new Map()——创建Map对象;
map.set(key, val)——添加一个键值对;
map.get(key)——通过键找到val值,如果不存在key,返回undefined;
map.has(key)——判断map是否存在键key,存在返回true,不存在返回false;
map.delete(key)——删除指定键;
map.clear()——清空map中所有的内容;
map.size——map中键值对的数量; - 遍历与迭代
map.keys()——返回map所有键的可迭代对象;
map.values()——返回map所有值的可迭代对象;
map.entries()——返回map所有键值对的可迭代对象;
也可以通过map进行遍历:
map.forEach((key,val)=>{
操作
})
- 从数组,对象创建Map:
还可以通过Object.entires(obj)方法将对象转为数组
let obj = {
xiaoming:'heiheihei',
xiaohong:'hahahahah'
}
let map = new Map(Object.entries(obj))
console.log(map)
Object.fromEntries()把数组和Map转为对象
let obj = Object.fromEntries([
['key1','val1'],
['key2','val2'],
['key3','val3'],
])
console.log(obj)
8.集合Set
- 定义:一系列值得集合(没有键),每个值都只能出现一次
- 与数组相比优点:arr.find 判断元素是否重复会造成很大的性能开销
- 使用方法:
new Set([iter])——创建一个集合,如果传入了一个可迭代变量(例如数组),就使用这个变量初始化集合
set.add(val)——向集合中添加一个元素val
set.delete(val)——删除集合中的val
set.has(val)——判断集合中是否存在val,存在返回true,否则返回false
set.clear()——清空集合中所有的元素
set.size——返回集合中元素的数量 - 集合迭代:for…of 和forEach
let set = new Set(['xiaoming','xiaohong','xiaoli'])//使用数组初始化集合
for(let val of set){
console.log(val)
}
set.forEach((val,valAgain,set)=>{
console.log(val)
})
weakset
缺点:1.不能传入非对象类型的参数,2.不可迭代,3.没有forEach()属性,4.没有 size 属性
区别:
原始存储在栈内,引用存储在堆内,
- 赋值:
原始:传 值 ,
引用赋值:两个引用对象使用同一个地址,赋 引用的对象 , - 比较:
原始类型:比较 【值】
引用类型:比较 【引用】 是否指向同一个对象,即使两个对象属性一样,但是两个对象仍然不相等 - 函数传参:
原始类型:作为形参局部会被销毁, 不会影响实参的值(函数外)
引用类型:改变引用对象,即使局部函数销毁,函数内的操作改变影响实参
浅拷贝:(仅实现拷贝值)
Object.assign 拷贝所有 属性值 到 新对象。如果属性值是 对象 ,拷贝的是地址。
let a = {
age: 1
}
let b = Object.assign({}, a)
a.age = 2
console.log(b.age) // 1
深拷贝:(仅实现拷贝值)
JSON.parse(JSON.stringify(a))
let a = {
age: 1,
jobs: {
first: 'IT'
}
}
let b = JSON.parse(JSON.stringify(a))
a.jobs.first = 'PM'
console.log(b.jobs.first) // IT
- 诸多局限:
1、会忽略undifined;2、会忽略symbol;3、不能序列化函数;4、不能解决循环引用的对象。
自定义深拷贝函数:
deepClone( ) 通过判断参数对象类型,创建响应对象作为返回
4.常用运算符及其优先级
算术:加减乘除取余自增减,
赋值:和等沾边
逻辑:与或非
关系:比较
三目:条件选择
5.语句:
- if 条件选择
- do while,while,for 循环
- for in 与 for of 区别:
for…in ES5标准,遍历键(key)(数组也是对象,索引作为属性,不建议,输出顺序不固定)以原始插入顺序迭代对象的可枚举属性(自定义属性),(内置属性Length就不可使用)使用前检查对象的值是否是null和undefined,是则不执行循环体
for…of ES6标准,遍历键值(value),可使用在数组,Set,Map某些类似数组的对象,Generator对象以及字符串 - try-catch 语句,处理异常的一种标准方式,try-catch 能够让我们实现自己的错误处理机制。使用 try-catch 最适合处理那些我们无法控制的错误。
try{ // 可能会导致错误的代码 } catch(error){ // 在错误发生时怎么处理 }
在 try-catch 语句中是可选的,但 finally 子句一经使用,其代码无论如何都会执行。
function testFinally(){
try {
return 2;
} catch (error){
return 1;
} finally {
return 0;
}
}
5.1错误类型:
Error:基类型,其他错误类型都继承自该类型。主要目的是供开发人员抛出自定义错误。
EvalError:使用 eval()函数 而发生异常(没有把 eval()当成函数调用)时被抛出。比如:以非直接调用的方式使用 eval 属性的值,或者为 eval 属性赋值。
new eval(); //抛出 EvalError
eval = foo; //抛出 EvalError
RangeError:在数值超出相应范围时触发
ReferenceError:在访问不存在的变量时发生。
SyntaxError:在我们把语法错误的 JavaScript 字符串传入 eval()函数时
TypeError:变量中保存着意外的类型时,或者在访问不存在的方法。最常发生类型错误的情况,就是传递给函数的参数事先未经检查,结果传入类型与预期类型不相符
URIError:在使用 encodeURI()或 decodeURI(),而 URI 格式不正确时,就会导致 URIError 错误。这种错误也很少见,因为前面说的这两个函数的容错性非常高。
6.箭头函数
- 定义:
( ) 中定义参数,如果只有一个参数,可以不写
{ } 定义函数体,如果只有返回值,可不写 return
function fun() {
return 100;
}
正常函数调用:
const fun = function() {
return 100;
}
箭头函数:
const fun = () => 100;
- 箭头函数与普通函数区别:
1.this 指向不同
2.普通函数,谁调用函数,this 动态指向谁;箭头函数,在哪里定义,this指向谁,比如计时器指向window
3.箭头函数没有构造能力,不能用new 构建构造函数,不能重复利用。但普通函数可以,也会自动生成prototype属性,同时会创建arguments对象
4.箭头函数不能通过bind,call,apply改变this值,但可以调用其方法
7.BOM对象属性
-
概念:提供独立于内容而与浏览器窗口进行交互的对象,核心对象window.
-
window 对象常见事件:
窗口加载事件
调整窗口大小事件 -
定时器
setTimeout() 定时器,延迟时间
clearTimeout( ) 停止定时器
setInterval( ) 定时器,循环间隔时间
clearInterval( )
this指向 -
JS执行机制
单线程
一个问题
同步与异步:
同步:都在主线程上执行,形成一个 执行栈
前一个任务结束后再执行后一个任务异步:通过回调函数实现的,利用多核 CPU 的计算能力,HTML5 提出 Web Worker 标准,允许 JavaScript 脚本创建多个线程。在做这件事的同时,你还可以去处理其他事情
异步任务有以下三种类型 普通事件,如click,resize等 资源加载,如load,error等 定时器,包括setInterval,setTimeout等
执行机制:异步任务相关回调函数添加到任务队列(执行栈)中,先执行战中同步任务,异步任务放入队列,所有同步执行完毕,异步结束等待,进入执行栈执行。不断完成事件循环,