1 js代码执行顺序
JavaScript 代码执行顺序:顺序执行 JavaScript 引擎并非一行一行地分析和执行程序,而是一段一段地分析执行。当执行一段代码的时候,会进行一个“准备工作”,叫做"执行上下文 就三种,全局代码、函数代码、eval代码。
2 数据类型
基本数据类型有:string number boolean const let symbol null undefined ;
复杂数据类型: object function array
注意:const let 是块级作用域,而且不存在变量提升,不可重复声明,存在暂时性死区。
2.1 作用域和作用域链
作用域:变量和函数能被有效访问的区域或者集合。作用域决定了代码块之间的资源可访问性。javascript采用的静态作用域,也可以称为词法作意思是说作用域是在定义的时候就创建了, 而不是运行的时候。 ES6前分为全局作用域和函数作用域,ES6增加了let和const块级作用域,在大括号内有效。
作用域链:全局声明的变量,在函数内也可以使用,在函数内声明的变量在全局不能使用,在函数内在声明一个函数,在第二个函数内使用一个变量是先在本函数内查找没有就去父级函数内查找,没有再去全局查找。这就是作用域链。
3 类型转换
3.1显示类型转换:
-
number():Boolean类型true=>1,false=>0;string类型:数字开头直接转换,空字符串转换为0 ,不是数字开头NaN;对象数据类型:valueOf()如果转换后还是复杂数据类型=>toString()
-
toString():array类型:每个元素转换拼接并用逗号隔开,空 对 空。object: “[object objectName]” objectName=>对象类名称。null和undefined没有tostring()方法,需要调用string()方法。
-
boolean():
undefined,null,false,NaN,'',0,-0为false,其他都为true。
3.2隐式类型转换:
递增和递减操作符遵循下列规则:非数字时用number()转换。 逻辑非 :与boolean()转换相反。 逻辑与
- 如果第一个操作数是对象,则返回第二个操作数;
- 如果第二个操作数是对象,则只有在第一个操作数的求值结果为 true 的情况下才会返回该对象;
- 如果两个操作数都是对象,则返回第二个操作数;
- 如果有一个操作数是 null,则返回 null;
- 如果有一个操作数是 NaN,则返回 NaN;
- 如果有一个操作数是 undefined,则返回 undefined。 逻辑或
- 如果第一个操作数是对象,则返回第一个操作数;
- 如果第一个操作数的求值结果为 false,则返回第二个操作数;
- 如果两个操作数都是对象,则返回第一个操作数;
- 如果两个操作数都是 null,则返回 null;
- 如果两个操作数都是 NaN,则返回 NaN;
- 如果两个操作数都是 undefined,则返回 undefined。
关系操作符 - 如果两个操作数都是数值,则执行数值比较。
- 如果两个操作数都是字符串,则比较两个字符串对应的字符编码值。
- 如果一个操作数是数值,则将另一个操作数转换为一个数值,然后执行数值比较。
- 如果一个操作数是对象,则调用这个对象的 valueOf()方法,用得到的结果按照前面的规则执行比较。如果对象没有 valueOf()方法,则调用 toString()方法,并用得到的结果根据前面的规则执行比较。
- 如果一个操作数是布尔值,则先将其转换为数值,然后再执行比较。
相等和不相等 (==与!==) - 对象与对象比较地址
- 对象与字符串,对象转字符串
- NaN和自己,其他值都不相等
- null和undefined相等
- 其他类型两边类型不同比较转换为数字。
4 分支语句
if else语句
if(布尔表达式){
//如果布尔表达式的值为true
}else{
//如果布尔表达式的值为false
}
switch case 语句语法格式如下:
switch(expression){
case value :
//语句
break; //可选
case value :
//语句
break; //可选
//你可以有任意数量的case语句
default : //可选
//语句
}
5循环遍历
5.1基础
while循环和do…while 循环
while( 布尔表达式 ) {
//循环内容
}
do {
//代码语句
}while(布尔表达式);
for循环
for(初始化; 布尔表达式; 更新) {
//代码语句
}
5.2对象遍历:
1.for in:自身和继承属性,可枚举,不含Symbol
2.Object.keys(obj):可枚举,不含Symbol,自身
3.Object.values(obj):可枚举,不含Symbol,自身
4.Object.getOwnPropertyNames(obj):自身所有属性,不含Symbol
5.Reflect.ownKeys(obj):自身所有属性
let se={'ss':"sfg","ef":"dvb"}
Object.keys(se) //["ss","ef"]
Object.values(se)//["sfg","dvb"]
5.3数组遍历:
forEach,map,filter,every,some,reduce等.
var arr=[10,20,30];
arr.forEach(function(ele,index){
console.log(ele +'==='+index)
})
//10===0
//20===1
//30===2
5.4字符串遍历:
for in
5.5 Set数据结构:
Set.prototype.keys():返回键名的遍历器
Set.prototype.values():返回键值的遍历器
Set.prototype.entries():返回键值对的遍历器
Set.prototype.forEach():回调函数遍历每个成员
let set = new Set(['red', 'green', 'blue']);
set.keys() //['red', 'green', 'blue']
set.values()//['red', 'green', 'blue']
set.entries()//[["red", "red"], ["green", "green"],["blue", "blue"]]
5.6Map数据结构:
Map.prototype.keys():返回键名的遍历器
Map.prototype.values():返回键值的遍历器
Map.prototype.entries():返回键值对的遍历器
Map.prototype.forEach():回调函数遍历每个成员
const map = new Map([
['F', 'no'],
['T', 'yes'],
]);
map.keys() //["F","T"]
map.values() //["no","yes"]
map.entries() //[["F", "no"],["T" ,"yes"]]
// 或者
for (let [key, value] of map.entries()) {
console.log(key, value);
}
// "F" "no"
// "T" "yes"
6函数
6.1创建函数的三种方式
函数声明,函数表达式,函数构造法var sum3=new Function('n1','n2','return n1+n2');
6.2arguments
函数的所有参数集合,是一个伪数组,不是真正的数组,有数组的length属性。
6.3默认值
允许为函数的参数设置默认值,一般默认值放在最后。
6.4rest 参数
ES6 引入 rest 参数(形式为...变量名),用于获取函数的多余参数,这样就不需要使用arguments对象了。rest 参数搭配的变量是一个数组,该变量将多余的参数放入数组中。
function add(...values) {
let sum = 0;
for (var val of values) {
sum += val;
}
return sum;
}
add(2, 5, 3) // 10
6.5箭头函数
var f = v => v;
// 等同于
var f = function (v) {
return v;
};
6.6this指向
- 箭头函数:包裹箭头函数的第一个普通函数的中的this
- bind call apply 第一个参数
- 普通函数:new调用:实例化对象;foo() => window;obj.foo() => obj
- 匿名函数指向window.
7对象
7.1创建对象的方式
构造法=>工厂模式,自定义构造函数,字面量。
当然对象的键( key )也可以是多词属性,但必须加引号,使用的时候,必须使用方括号( [] )读取:
let user = {
name : 'leo',
"my interest" : ["coding", "football", "cycling"]
}
user["my interest"]; // ["coding", "football", "cycling"]
delete user["my interest"];
对象进行属性对增删改查操作:
// 增加属性
user.addr = "China";
// user => {name: "leo", age: 18, addr: "China"}
// 删除属性
delete user.addr
// user => {name: "leo", age: 18}
// 修改属性
user.age = 20;
// user => {name: "leo", age: 20}
// 查找属性
user.age;
// 20
8构造函数
8.1定义
构造函数就是一个普通函数,内部使用this声明变量;使用new生产实例。在new时this指向生产的实例对象。
8.2构造函数的属性
-
私有属性 => var声明;
-
公有属性 => this或者原型对象属性
-
静态属性 => 构造函数上的属性和方法,不需要实例(比如:Person.xxx)class类定义静态属性和方法在前面加上
staic或者在类外用 类名.xx
8.3prototypeof 模式
每个构造函数都有一个prototype属性,指向一个对象。构造函数创建的实例都会继承它的属性和方法。将构造函数内不变的属性和方法定义在原型对象上。
8.4常用的属性方法和运算符
-
constructor属性:构造函数原型对象上的一个属性,正常情况指回构造函数。
-
instanceof 运算符:A(实例对象) instanceof B(构造函数) A是否在B的原型上。
-
isPrototypeOf() 方法: 用来判断原型对象和实例对象的关系;
Person.prototype(原型对象).isPrototypeOf(p1) //true -
hasOwnproperty()方法:每个实例都有此方法,用来判断属性是本地属性还是原型属性。
p1.hasOwnproperty("ame") -
in 运算符 :判断实例是否有某个属性;
'name' in p1
8.5继承
//寄生组合继承
//父类
function Animal (age,name){
this.age=age;
this.name=name;
this.foods=['水果','ls']
}
// 父类原型方法
Animal.prototype.run =function(){
console.log(this.name+'runhsii')
}
function Cat (age,name){
Animal.call(this,age,name)
}
// 寄生继承函数;
// Object.create() 创建一个对象,新创建的对象的__proto__指向括号中的对象。
function inheritFrom(o){
var t =Object.create(o);
t.constructor=Cat;
return t;
}
Cat.prototype=inheritFrom(Animal.prototype);
//组合继承
function Animal() {
this.name = 'cat'
this.msg = {
age: 9
}
}
Animal.prototype.greet = function () {
console.log('hehe')
}
function Dog() {
Animal.call(this) // 核心一步
}
Dog.prototype = new Animal() // 核心一步
const a=new Dog()
//extends继承
class A {}
class B extends A {
constructor() {
super();
}
}
8.6原型和原型链
原型:构造函数都有一个属性叫prototype,指向一个对象,对象中存储着构造函数创建的实例的公用属性和方法,这个对象就是原型,原行中有一个属性加constructor指回构造函数但是这个属性可以更改,更改了就是继承。
原型链:每一个JavaScript对象(除了 null )都具有的一个属性,叫"__proto__",这个属性会指向该对象的原型,最终指向object.prototype=>null。
8.7闭包
闭包是指那些能够访问自由变量的函数。闭包 = 函数 + 函数能够访问的自由变量 自由变量是指在函数中使用的,但既不是函数参数也不是函数的局部变量的变量。