#1、
目录
1、浏览器是如何解析html文件的?
(1)解析html,创建DOM树,下载css,js文件
(2) 解析css文件,创建css规则树
(3)将DOM树和css规则树结合并创建渲染树
(4)布局绘制
#2、重绘和回流
重绘:当页面中一些元素外观(颜色)发生改变时就会产生重绘
回流:当页面中一些元素的布局(宽高)发生改变时就会产生回流
回流一定重绘,重绘不一定回流
常见引起回流操作
添加、删除(回流+重绘)
隐藏 display(回流+重绘) visibility(重绘)
#3、浏览器里面有js解释器(v8引擎),所以可以解释js文件
#4、命名重复的解决方法:1.对象化 2.作用域
#5、浏览器是怎么执行js文件的:1.语法分析 2.预编译 3.执行代码
#6、如何编写高性能的JavaScript:
1.遵循严格模式:‘use strict’
2.将JS脚本放在页面底部文件,加快渲染页面
3.将js脚本将脚本成组打包,减少请求
4.尽量使用局部变量来保存全局变量
5.减少使用闭包
6.使用window对象属性方法时省略window;
7.尽量减少对象成员嵌套
8.缓存DOM节点的访问
9.通过避免使用eavl()和Fulnction()构造器
10.给setTimeout()setInterval()传函数而不是字符创作为参数;
11.尽量使用直接量创建对象和数组
12.最小化重绘(repaint)和回流(reflow)
一、js(es5)
1、js了解
js:解释性语言
js包含三部分:
ECMAScript
DOM:文档对象模型,提供一些访问和操作网页内容的方法
BOM:浏览对象模型,提供一些访问和操作浏览器内容的方法
注释行:chtl+/
块注释:shift+alt+a
把js文件引入到html:
行内
外部:<script src="js文件路径"></script> 内部:<script> 语句 </script>
2、变量
声明变量:
var 变量名(es5语法) let 变量名(es6语法)
变量名命名规则:由字母、数字、下划线、$组成,不能以数字开头,不能是关键字,不能重复声明同一个变量(e5不会报错,es6会报错)
js严格区分大小写
初始化变量:
var 变量名; 变量名=值;
var 变量名=值;
console.log();打印语句,数值型数据打印字体颜色为蓝色,打印多个变量时用逗号分隔
console.dir();打印出来以对象的形式显示
3、js数据类型
typeof()用于检测数据类型
(1)基本数据类型
number
isNaN()检测一个值是否不是一个数值,Infinity()正无穷
Math
-
Math.PI;表示pi值
-
Math.ceil( );向上取值
-
Math.floor( );向下取值
-
Math.round( );四舍五入
-
Math.Max();最大值
-
Math.random( );生成0到1之间的随机数,包括0不包括1
indexOf(参数1,参数2) 查找,找到返回其下标,没有返回-1,如有多个则返回第一个下标
参数2是从第几位开始查找,省略时默认从下标0开始查找
数值的扩展:
bigInt 表示一个大的值
在打印值后面加n
string
字符串:' '、" "、``(es6),+号用于字符串拼接、$+{}(es6``里面) padStart(参数1,参数2):参数1是结果长度,对象前面添加参数2
方法
-
1、length :获取字符串长度
-
2、chartAt(下标 ) :获取指定位置的字符
-
3、indexOf( ):查找字符串里是否包含某个字符,有返回下标,没有返回-1
-
4、match(正则表达式):字符串匹配查找
-
5、replace( 要查找到的字符,要替换的字符):字符串替换
-
6、字符串.repeat(重复次数,不能小于-1) 字符串重复打印
-
7、split("字符"):把一个字符串切割成一个数组,从传的字符对应位置切割,传的字符会消失不存在
-
8、trim( ):删除字符串前后空格
-
9、字符串截取:
-
substring(start,end) 开始下标位置start,结束下标位置end,包含start,不包含end,不支持负数
-
substr(start,length) 从start开始截取,截取长度为length的字符串,支持负数,为负数时是从后往前数
-
slice(start,end) 开始下标位置start,结束下标位置end,包含start,不包含end,支持负数,为负数时是从后往前数
-
-
10、toLocaleLowerCase():大写字母转小写 11、toLocaleUpperCase():小写字母转大写
-
12、字符串填充:padStart(length,str)
-
13、判断是否以某一个字符开始:stratsWith(' ');
-
14、判断是否以某一个字符结束:endsWith(' ');
-
15、includes('要查找字符串');扩展
-
16、charCodeAt(下标) 查找指定位置的字符编码
布尔型
true false
Boolean(值);所有引用类型转为Boolean都为true
空字符串、false、0、null、undefined、NaN转换为布尔
值为false
undefined:undefined
null:null,赋值为null时,typeof检测结果为object
(2)引用数据类型
引用数据类型保存在堆里
判断两个值是否相等:==
判断两个值和值的数据类型是否相等:===
数组
两个不同数组的值相同,==为false
创建数组:
let cArr=Array.of( ); 值为数组项
new Array();只有1个值时是数组长度,2个或多个时是数组的每一项
var 数组名=[ ],下标从0开始
Array.from({})
获取数组里的值:数组名[下标]
方法:
-
判断是否是一个数组:Array.isArray( )
-
添加值:
-
数组名.push( ); 在后面添加
-
数组名.unshift( ); 在前面添加
-
数组名[下标]=值;
-
数组名[数组名.length]=值;
-
-
删除值
-
数组名.pop( ); 删除前面
-
数组名.shift( ); 删除后面
-
delete 数组[ ]; 删除值后保留位置
-
-
查找
-
indexOf( ) 从前往后找
-
lastindexOf( ) 从后往前找
-
-
splice( ) 插入、替换、删除,会修改到原数组
-
数组名.splice(start,length,value1,value2...);
-
插入数据是在start(下标)之前插入,length为0
-
-
合并:数组1.concat(数组2,数组3);
[...数组1,...数组2]
-
every(function(current,index,array){return 条件 });
只要有一个值不满足条件结果为false,结束打印,函数里需要return一个需要的条件
-
some(function(current,index,array){return 条件 });
只要有一个值满足条件结果为true,结束打印,函数里需要return一个需要的条件
-
循环数组:forEach(function(循环出来的数组值,index,array){ });
-
遍历数组产生一个新的数组:
-
map(function(current,index,array){ });
-
-
累加、乘、除、减:
reduce(function(上一次结果,当前值,index,array){ },(initial初始值)); ,从前往后
reduceRight(function(上一次结果,当前值,index,array){ },(initial初始值));
-
颠倒数组 :
reverse( ); 会修改到原数组(用深拷贝方法)
-
slice(start,end); 截取数组里的某些值
-
sort( ) 排序,会改变原数组的值,对字符串排序时,只要有一个数值对象就会把字符转换为数值再进行比较
排序: sort(function(a,b){ /*if(a>b){ return -1; }*///从大到小 retrun a-b;//从小到大 })
筛选: filter(); 把想要的数据过滤出来 filter(function(a){ return 过滤条件; });
数组的扩展:
for(let k of arr.keys( )){ } 获得下标值,遍历对象
keys( ).next( );获得下标
values( ) 获取值
entries( ) 获取下标和值
Array.from(对象) 将对象转换成真正的数组
数组的浅拷贝与深拷贝
浅拷贝
var arr1=[10,20,30];
var arr2=arr1;
arr2[1]=200;
直接把数组1赋值给数组2
修改arr2时会修改到原数组里的数据
深拷贝
var arr1=[10,20,30];
var arr2=[];
for(var i=0;i小于arr1.length;i++){
arr3[i]=arr1[i];
}
把数组1的值拿出来赋值给数组2
修改arr2时不会修改到原数组里的数据
实现深拷贝方法:
for( )
forEach()
map()
扩展运算符:...
对象
var 对象名={ 属性名1:值1, 属性名2:值2, 属性名3:值3 }
valueOf( ) 每个对象都有,如果对象自身定义了一个valueOf就不会用到原型
属性
in 对象:判断一个对象上是否有某个属性
获取对象属性值:
对象名.属性名
对象['属性名']
对象[变量]
对象1{对象2}:对象1==对象2值为true
对象1={ },重新赋值后 对象1==对象2值为false
添加属性:
对象.要添加的属性=属性值
对象['属性']=属性值
删除和方法
delete 对象.属性;
创建对象的方法:
字面量(直接创建)
构造函数:Object String Boolean Number
工厂模式
new Object console.dir()只针对引用数据类型
Object.create(值)值不能省略
在对象的原型上添加方法
对象.prototype.方法名=function( ){
console.log(this[i]);
}
对象的扩展
for(let in 对象) 循环对象
Object.keys( 对象);属性名
Object.values(对象); 值
Object.entries(对象); 属性名 值
原型
每个对象都有一个与之对应的对象(原型对象)Prototype
每个对象的原型对象都不一样
函数里的是Prototype
获取对象原型:对象.Prototype
所有(实例化)对象的原型是[[Prototype]]
获取对象原型:对象.__proto__
-
所有实例化的对象的原型[[Prototype]] (proto)指向对应构造函数的原型Prototype
-
所有构造函数的原型对象,Prototype的原型[[Prototype]] (proto)指向内置构造函数Object的原型Prototype
-
所有Object的[[Prototype]] (proto)指向null
原型链:一个对象在使用某个方法或属性时,首先在自己属性里找,如果没有,则去原型上找,如原型上没有就去原型对象的原型上找,如果到最后没找到会报错或undefined
函数
声明函数:function 函数名(形参){ }
函数调用:函数名(实参);
需要调用函数才可以执行函数里面的代码块,函数可以多次调用
return:返回值,只能出现在函数里,return后面的语句不会执行,每个函数都会有一个结果值
每个函数里面都有一个arguments数组,传的参数都在里面
自运行函数(立即执行函数)
(function(){ })();页面一加载就执行
递归函数
自己调用自己
构造函数
函数名首字母大写,函数里面会出现this,this指向的是实例化对象
实例化对象:new 函数名();
没有return时默认返回this
当普通函数时,this指向window
instanceof 判断对象是否由某个构造函数实例化出来的
内置构造函数:
Date()
now=new Date( )
获取时间戳:now.getTime( );
获取未来时间戳:now.setTime( 时间戳);
-
now.getFullYear( );获取年
-
now.getMonth()+1; 获取月
-
now.getDAY( ); 周几
-
now.getDate( ); 获取日
-
now.getHours( ); 时
-
now.getMinutes( ); 分
-
now.getSecond( ); 秒
回调函数
调用一个函数时传的参数为函数(回调函数)
闭包
函数里面返回了函数,并且函数外面用到了函数里面的变量,将函数外面和里面搭建起来看桥梁,return一个函数
作用:可以数据存储(保留上次执行结果)
缺点:会在成内存泄漏(慎用),变量手动设置为null可回收变量
函数扩展
形参设置默认值 function fn(obj={ }){ console.log(obj); } fn({x:10,y:20}); fn()
箭头函数
(参数)=>{函数体} 某些情况下小括号和花括号可以省略
箭头函数里没有argument
箭头函数里面的this在创建的时候就已经确定了,
小括号:有一个形参时可以省
花括号:只有return语句时可以省略并且return也可以省略
let fn2=()=>{}
(3)数据类型转换
转换为字符串
数组转字符串
-
数组名.toString()
-
数组名.join(分隔符);省略分隔符默认以逗号分隔
变量名.toString();null、undefined一般不能.toString转为字符串
json格式对象转为字符串:JSON.stringify()
字符串转换为对象
json格式字符串转为对象:JSON.parse
new String( ) 字符串转换为对象
转换为number
parseInt(值);从第一个字符开始判断,如果第一个字符为数字字符,就继续向后判断,直到遇到非数字字符停止
NaN与任何值都不相等,包括它自身
转换为布尔型
Boolean(值);所有引用类型转为Boolean都为true,空字符串、false、0、null、underfined、NaN转换为布尔值为false
3、this对象
直接打印this会打印window,window是js的顶层对象
函数里面的this,谁调用这个函数,this就指向谁
this无处不在,但只有在函数里才使用
改变this指向:
函数.bind(对象)(值); 函数里的this指向对象
函数.call(obj); this指向obj 函数.call(obj.值)
函数.apply(obj,[值1,值2,....])
4、if语句、switch语句
if语句
if(判断条件){ 语句块 },判断条件成立则执行语句块
if(值){},值为隐式转换条件,可以自动转换Boolean型
if(判断条件){语句块1}
else{语句块2},if条件不成立则执行语句块2
switch语句
switch(值){
case :
break;
case :
break;
default: //前面条件都不满足时执行
}
5、循环语句
for语句
for(循环控制变量;循环控制条件;循环控制变量自增自减){ },如有多个判断条件以逗号分隔,以最后一个条件为准
document.write();把内容写到页面
for...in...
for(var k in 对象){ }//循环对象
换行:添加标签
while语句
while(循环条件){语句块}
do...while语句
do{
语句块
}while(循环条件)
6、变量提升
执行程序时,会把声明提升到最前面,赋值不会提升,变量提升后会把函数提升
函数可以在声明函数前调用函数
变量和函数重名时:变量不赋值指函数,赋值指变量
7、作用域
全局作用域:在顶层代码里面
go(全局对象)
局部作用域:在函数里面,局部可以用全局变量,全局变量在局部里改变了值,在全局里也会改变值,全局不可以用局部变量
Ao(局部对象)
局部和全局变量重名时,局部变量优先
8、操作符
逻辑操作符
非: ! ,取反,结果为Boolean值
与:&& ,第一个值为真时返回第二个值,第一个值为假时返回第一个值
或:||,第一个值为真时返回第一个值,第一个值为假时返回第二个值
优先级:()>! >&&>||
9、DOM
document:
获取标签:document.querySelector(css选择器); 修改标签样式:标签.style.属性=’属性值’ 修改标签内容:innerHTML=’内容’ 能在引号里写标签 innerText=’****内容’ 不能识别标签
事件
事件三要素:事件源 事件 事件处理函数
click 使用时前面加on 即onclick
10、定时器
js是单线程
同步:等上一行代码执行完后才能执行下一行
异步:全部代码执行完成后才执行异步
定时器是异步
setInterval(function(){},(Interval ms));
清除定时器:clearInterval( );
setTimeout(function(){},(Timeout ms));延迟
清除:clearTimeout( );
11、数据劫持
Object.defineProperty(obj,'需要拦截的属性',{})
12、正则表达式
变量.match( )
正则.excute('字符')
创建正则表达式:
var a=/abc/
var a=new RegExp('abc')
属性:
i:不区分大小写
g:全局
m:换行
中括号[ ]
用于查找某个范围内的字符
var reg=/[ab][cd][d]/g; var str="abcd"; str.match(reg);//["bcd"];
插入符^放到[]里边表示"非"的意思
var reg=/[^a][^b]/g;//插入符^放到[]里边表示"非"的意思 var str="ab1cd"; str.match(reg);//["b1","cd"];
在括号里可以加入"|"表示"或"的意思,"|"操作符两边放匹配规则
var reg=/(abc|bcd)/g; var str="abc"; str.match(reg);//["abc"];//该规则既能匹配出字符串"abc" str="bcd"; str.match(reg);//["bcd"];//该规则又能匹配出字符串"bcd" reg=/(abc|bcd)[0-9]/g; //匹配规则可以任意组合 str="bcd2"; str.match(reg);//["bcd2"]
元字符
元字符 | 描述 |
---|---|
\w | 查找单词字符(字母+数字+下划线) |
\W | 查找非单词字符 |
\d | 查找数字 |
\D | 查找非数字字符 |
\s | 查找空白字符 |
\S | 查找非空白字符 |
\b | 匹配单词边界 |
\B | 匹配非单词边界 |
\t | 查找制表符 |
\n | 查找换行符 |
\f | 查找换页符 |
\v | 查找垂直制表符 |
\uXXXX | 查找以十六进制规定的Unicode字符 |
. | (点号)查找单个字符,除了换行和行结束符 |
"\w"---->[0-9A-z_],(word)单词字符,字母字符
"\d"---->[0-9]
量词
量词 | 描述 |
---|---|
n+ | 匹配任何包含至少一个n的字符串 同{1,} |
n* | 匹配任何包含零个或多个n的字符串 同{0,} |
n? | 匹配任何包含零个或一个n的字符串 同{0,1} |
n{X} | 匹配包含X 个n 的序列的字符串 |
n{X,Y} | 匹配任何包含X 个至Y 个n 的序列的字符串 |
n{X,} | 匹配包含至少X 个n 的序列的字符串 |
n$ | 匹配任何结尾为n 的字符串 |
^n | 匹配任何开头为n 的字符串 |
S(?=n) | 匹配任何其后紧接指定字符串n 的字符串S |
S(?!n) | 匹配任何其后没有紧接指定字符串n 的字符串S |
贪婪匹配:/值+/ 单个或多个都会匹配出来
非贪婪:/ / 在量词后加? 单个打印
弹窗:
window.alert() 阻断代码执行
confirm() 点击确认打印true,取消打印false
window.prompt() 可以输入
debugger;断点
window.open(地址)
二、js(es6)
1、var、let、const的区别
var
-
变量提升
-
可做window属性,声明全局变量
-
不初始化不会报错,结果为undefined
let:
-
不能实现变量提升
-
在全局作用域里声明不会作为window属性
-
只在当前块级作用域有效
-
不能重复声明同一个一个变量
const
-
声明的是一个常数
-
在全局作用域里声明不会作为window属性
-
声明时赋值,值不能更改
-
不能实现变量提升
-
不能重复声明同一个变量
-
声明的变量只是地址不能更改,但是地址所对应的数据是可以更改的
2、解构
数组的解构
用在函数里时:形参加[ ]
[a,b,c]=[100,200,300]; 一一对应
[a,b,c=100]=[100,200]
可嵌套
可忽略 [a,,c]=[100,200,300]
交换两个变量的值:[a,b]=[b,a];
扩展运算符 ...
[a,...a1]=[100,200,300,400];
对象的解构
模块化解构
<script type="module"> import 变量 from 'js文件路径';//接收js文件 //js文件:export default 值; 从js文件导出到module </script>
import {解构} from 'js路径';
export 语句;可以导出多个语句
3、对象新增
属性简写
let sname=' ',age=' '; 对象={sname,age}; 对象={[ ]:' '};
对象新增方法
比较两个值是否相等
Object.is( , ) ,等同于===
Object.is(NaN,NaN) 结果true
Object.is(+0,-0) 结果false
对象合并
Object.assign(对象1,对象2)
{...对象1,...对象2}
循环
添加属性
Object.dedfineProperty(对象,'属性',{ value:'值', writable:true(默认false), enumerable:true//为真时,可枚举,只有可枚举才能循环对象 });