js三座大山:原型和原型链 作用域和闭包 异步和单线程
引用类型:对象 数组 函数 因为指针引用的是一个空间 所以叫做引用类型 目的是为了避免浪费很大的内存空间 引用类型可以无限制扩展属性
typeof (undefined string number boolean object function)只能区分值类型 但是不能区分引用类型 对象和数组{}[]null均打印object
变量计算:强制类型转换值类型转换
1.字符串拼接
var b = "110" +10
2.==
100 == "100"
0 == ""
null == undefined
3.if语句0 nan undefined null "" 最后都判断为false
!window.abc a=100 !!a 最后判断为 true
js中的内置函数:不考虑浏览器的环境单纯作为语言来讲内置了构造函数 Number String Boolean Object Function Array Date RegExp Error
js中内置对象:json和math, JSON.stringfy和JSON.parses 也是一种数据格式
构造函数的特点 函数名称大写 默认会有return this
重点关注this 对象无限添加属性
intanceof判断一个函数Array是否是一个变量[]的构造函数
原型规则 4条
1.所有的引用类型(数组 对象 函数)都具有对象特性,既可以任由扩展属性除了null
2.所有的引用类型(数组 对象 函数)都有一个proto属性!隐式原型!,属性值是一个普通对象 所有函数都有一个prototype属性,属性值也是个对象
3.所有引用类型(数组对象函数)proto属性值指向他的构造函数“prototype”属性值
4.试图在找一个对象的属性时 如果对象本身没有会去查找自身的proto隐式原型查找
原型链
1.描述new一个对象的例子
创建一个新对象 this来引用这个对象然后就可以给this扩展属性 类似于a={} a.age =18 return a;
练习
1.对象属性 下面的第一个例子 this指向调用者
2.普通函数 window
3.call apply bind call和apply的区别在于后面参数传递apply为数组 而bind与这两个的区别在于返回的是函数需要.bind(aaa)()执行
函数表达式
作用域:js没有块级作用域 只有函数和全局作用域
作用域链:当前作用域没有的变量即自由变量,于是去父级作用域去找,函数的父级作用域是函数定义时的作用域不是执行的时候
1.变量提升变量定义/函数声明
声明提前 也就是相当于var age; age = 100 函数定义就是函数声明所以就是把整个函数定义提前 而变量是变量定义+变量赋值两个操作 所已 这就是为什么函数表达式不会起作用比如var a = function(){} 提前的将是 var a = undefined
10个a标签都初始化好之后放进页面中,监听函数的执行时间是不确定的,当我们点击的时候i已经循环到10 所以结果将是每个标签点击都为10
创建 函数作用域 声明了10个函数
闭包的应用 封装变量收敛权限(多用于单例模式)
判断用户是否是第一次加载对list进行封装 函数外部是拿不到list的 所以你将不会改到list收敛权限
异步单线程:js是单线程所以才有的异步 alert(200)会阻塞程序的执行
对比异步和同步
1.setTimeout 同步和异步的区别是阻塞
2.前端使用异步的场景有哪些,什么时候需要异步
在可能发生等待的时候 1.setTimeout/2.网络请求 ajax<img>加载/3.事件绑定不一样的地方是可以执行多次 等待过程中不能阻塞程序运行
单线程 下图没有时间的设置和设置为0是一样的 单线程一次只能做一件事打印100 300 200
其他知识点
这里还有一个String.padStart(),比如let str= "5", str.padStart(2,"0") //'05' 以0从头开始填充到两位,如果是“0005”则返回“0005”
webapi
回顾js基础 表面看来并不能用于工作中开发代码(这里要引入两个标准一个是ecma标准,另一个是w3c标准) 也就是浏览器的开发是要遵循这两个标准的(ecma指定了js这门语言的语法,w3c规定了dom bom 事件绑定 ajax 存储)w3c没有规定js基础相关的东西,他和ecma是不重合的,W3c不管变量类型/原型/作用域和异步语法,w3c只负责定义浏览器中js操作页面的api和全局变量,他们的组合规范了web开发
dom本质:html和xml规则是一样的浏览器拿到html的页面的时候需要把这个页面渲染并且还要让浏览器能解析js 浏览器最喜欢处理结构化的东西拿到html的代码的时候就会将他结构化dom html代码就是浏览器将他结构化成j浏览器可识别的东西,如果js不能识别和操作那js将不能运行
dom操作
1.dom是哪种基本的数据结构 树形的数据结构
2.dom操作常用的api
针对树结构 :新增节点/获取父节点/获取子节点/删除节点/遍历
移动的时候 p2将不会在原来的地方存在
3.dom的attr和property的区别
attribute
attribute改的是html文档中的标签属性 而property改的是js对象内的属性是两个完全不一样的东西
nodeType 是数字类型 nodeName 是英文名字的描述
Bom拿到的是关于浏览器一些信息
navigator.userAgent
screen
location
事件绑定(通用事件绑定 事件冒泡 代理)
2.事件冒泡
事件冒泡:将事件绑定在div1上 冒泡的机制是p1 div1 body冒泡是事件向上 上图的效果点击激活是先alert激活 然后e.stopPropatation() 阻止冒泡蔓延到body
冒泡事件的应用 代理
虽然我们在div1上绑定的监听事件 但是target是告诉我们在哪里触发的事件即a标签
target 事件属性可返回事件的目标节点(触发该事件的节点),如生成事件的元素、文档或窗口
代理的好处:代码简洁 减少浏览器内存占用
ajax(XMLHttpRequest 状态码说明 跨域)
1.手动编写ajax 不依赖第三方库
//3-10行为异步 异步的意思是最后执行 send之后xhr开始监听状态变化 ie低版本使用得是ActiveXObject
var xhr = new XHMLHttpRequest()
xhr.open('get','/a.txt',false);
xhr.onreadystatechange= function(){
if(xhr.readyState == 4){
if(xhr.status == 200){
//status是http标准的状态
console.log(xhr.responseText)
}
}
}
xhr.send(null)
2.跨域的几种实现方式跨域的原理(什么是跨域 jsonp)
浏览器同源策略不允许ajax访问其他接口(服务端是可以的)比如我们自己的网站用ajax来访问别人的接口
https 端口是443
jsonp实现原理:服务器动态拼一个js文件返回给我们
2服务端设置 http header
存储
1.cookie sessionStorage localStorage的区别
cookie本身用于客户端和服务器端通信的 但是它有本地存储的功能于是被借用
document.cookie = "name=oeschger";
document.cookie = "favorite_food=tripe";
alert(document.cookie);
sessionStorage在浏览器中当前页面会话关闭,sessionStorage将会清理
localStorage 永久存储
开发环境
1.页面的加载过程
浏览器根据DNS服务器得到域名的IP地址,向这个ip的机器发送http请求,服务器收到处理http请求 ,浏览器的到返回的内容,浏览器根据html结构生成dom树 再根据css生成cssom 在将dom树和cssom整合形成rendertree,最后浏览器根据rendertree开始渲染 遇到script会阻塞渲染因为js有权利改变dom的结构
window.onload和DOMContentLoaded的区别(window.onload必须加载完所有资源执行
DOMContentLoaded dom渲染完既可以执行不需要等待视频图片加载完)
页面加载的几种样例
首先加载页面的11行代码html代码,然后浏览器开始一步步从头分析 分析道link标签时 去加载css然后生成cssom的一个东西浏览器就会知道在div上要添加这样的样式,紧接着在继续解析的时候因为css已经解析完了再去渲染div生成divdom结构的时候就会将样式一次性渲染出来
为何把css放在head中:加载完css浏览器 知道规则在渲染body的时候将会把样式直接渲染出来,如果放在最后的话将会第一次显示默认的情况过了一会按照样式渲染
以上代码解析过程:首先输入url加载12行代码 然后浏览器开始 解析进入body渲染 到底9行的时候加载script 并执行这一行 js代码阻塞后续代码的渲染,js执行 完之后然后继续向下渲染
js放在最后:是因为不会阻塞html的结构渲染 第二是因为 script可以拿到所有的标签
以上代码:首先加载html的内容 然后开始渲染加载到图片的 时候异步请求 但是并不会阻碍整个dom的渲染
2.性能优化
1.构建工具合并静态资源
2.缓存通过连接名称控制缓存 不更换资源的名字 浏览器会帮我们缓存
3.
4.代理
5.缓存dom查询 第一个是每次循环都将执行dom查询做了10次
3.安全性
xss跨站请求攻击 再发布文章的时候的时候插入一段js代码 获取查看者的cookie发送到我自己的服务器 基本原理就是在向网站发布东西的时候提交 js代码 最好的预防就是将<替换成 其他内容
xsrf 和之前css看的不要将请求放在链接中的一个意思增加验证流程
类中的getter和setter set会监听到对象添加属性的操作 get会监听到获取的操作 用途实在底层封装框架
类身上的方法为静态方法
静态方法也会可以给子类调用
原方式函数继承
es6继承 extends
子类的构造函数必须执行一个函数就是super() 来执行父类的构造函数 否则会报错因为子类的构造函数将会把父类的构造函数给覆盖了
添加自己的属性
es6中的块级作用域 解决点击li监听函数弹出不一样的数字问题(1.let是利用块级作用域if for后面的花括号就是一个块 2.使用立即执行函数创建函数作用域解决)
let 相当于 var 但是没有预解析 同一个作用域里不能重复定义,在for循环的时候是父级作用域括号里是f花括号是子
const 在定义的时候必须要先赋值
对象引用的关系是不可以再重新引用其他的对象地址 但是对象内部的属性可以
Object.freeze 定一个数组不能去修改const arr = Object.freeze(["aaa","bbb"])
arr.push("a")将会报错 不能扩展
下图将会报错
没有块级作用域的时候我们是拿立即执行匿名函数来模拟的
解构赋值
let [a,b,c] = [12,5,6]
左右两边,结构格式要保持一致,数组的解构按从左至右依次赋值
解构json 解构对象的时候需要属性依次对应
let json = {
name="strive",
age:18
}
let {name,age}= json
给默认值 但是对null会无效 null会赋值给c
数组里可以交换位置
window和top是相同的
解构还用在import {}
函数传参解构
//函数传参给的默认值 如果不给的话将会报错 相当解构左右两边不等 如给了默认值当函数没有传参的时候将取默认值
function show({a = 1,b = 2} = {}){}
show()
4.字符串模板及新增
优点可以随意换行
str.indexOf 返回索引位置 -1
str.includes("a")返回 bool
检测 是否是以http开头
str.startsWith("http") str.endsWith
str.repeat(3) 重复3次
str.padStart(整个字符串长度,填充内容) 向前填充
"str".padEnd(6,"xxx")
函数变化
函数的默认参数
这个传值了 只有不给的时候才是没传
会报错 函数的参数将是默认定义的 和for循环有差别
扩展运算符 重置 剩余运算符...
对数组 和对象都管用
排序
剩余 剩余的意思是只能放在最后一个
复制数组 let arr = [1.2,3]
let b = [...arr]
函数真正的变化是箭头函数
当没有花括号的时候默认返回
完整的箭头函数
会执行undefined setTimeout由window执行
setTimeout 相当于一个数组 把方法存到数组里面 然后过段时间拿出来在全局环境下运行
let和const定义的变量不属于window
箭头函数中的this会绑定定义函数时候坐在的对象,不再是运行是所在的对象了
arguments在箭头函数中不存在 利用扩展运算符
箭头函数不能做构造函数使用 不能new
数组的热闹循环
数组最常见的就是循环
arr.forEach
arr.forEach(()=>{},123)回调函数是每循环一次调用一次
arr.filter
过滤:也是学要return的 过滤不想要的元素如果回调函数返回true该item项将回留下来
arr.some 数组里有一个选项符合条件就返回true 类似于查找的功能
arr.every 数组里面的所有元素都符合条件才会返回true
以上接受的参数一模一样 可以接受两个参数,第一个为回调函数 第二个是this的指向改变,第二个参数的几率很小
箭头函数绑定的this是定义时的this 不会改变 一下的结果打印还是window
arr.reduce 接受的参数 前一个和当前的item 项 index arr
reduce也是一个循环 求数组和
let arr = [1,2,3.4]
arr.reduce((pre,cur,index,arr)=>{ return pre+cur})
arr.redeceRight 打印81
for of 循环 最后一个[key,value]为数组解构
数组另增新的其他的东西
将类数组转为数组的方式,并且下标是0,1,2
类数组典型的特点是有length
2.Array.of()将一组值转为数组 类似于三点
3.数组本身的方法
find找出第一个复合条件的数组成员,如果没找到返回undefined
let arr = [1,2,3]
arr.find((val.index,arr)=>{ return val>2}) //打印3
findIndex没找到返回-1返回第一个符合条件的位置
3fill (填充的东西 开始位置 结束为止)
4.arr,IndexOf
arr.incluldes("a") 返回truefalse
findIndex传得是函数 indexOf是value项 返回的将是第一个符合条件的索引项位置
对象
对象的简介语法
对象里面不能用箭头函数
Obejct.is比较两个值相等 NaN
Object.is(NaN,NaN)
Object.assign 用来合并 复制对象
let json = {a:1}
let json 2 = {b:1,//a:2} 后面会覆盖前面的
let json3 = {c:3}
Object.assign({},json1,json2,json3)
Promise 主要的作用是解决异步回调问题,传统方式大部分用回调函数,事件
就是回调嵌套回调在嵌套回调
Promise.all必须确保所有的promise都是resolve的状态即都是成功的状态
symbol和generator
let syml = Symbol("aa") 不能new 他不是构造函数
json 使用for in循环 不能输出symbol的属性
generator 也是个函数 目的是解决异步问题 深度嵌套问题同promise 现在使用async
区分generator函数和普通函数*
function * show(){
yield //产出
}
genrator是分步骤完成的 done是说该函数是否完成,遇到return 完成
以上是手动调用 for..of自动遍历generator 但是不会遍历return的东西只会遍历yield的东西 还可以配合解构赋值
b是 剩余参数组成的数组
解决异步 第一步的结果传到第二步请求中
async
promise解决多层回调
generator解决多层回调
任何与网络请求有关的东西都try catch
以下三个网络请求没有必然关系的时候可以这么用 因为不能保证哪个网络请求先执行完后执行完