3.JavaScript

2019-11-25  本文已影响0人  helloyoucan

原文链接:https://github.com/helloyoucan/knowledge

JavaScript相关

1、声明相关
2、JS引擎
任务队列
  • 事件循环是通过任务队列机制来进行协调的。
  • 一个Event Loop中,可以有一个或者多个任务队列(task queue),一个任务队列就是一系列有序任务(task)的集合
  • 每个任务都要一 个任务源(task source),源自同一个任务源的task必须放到同一个任务队列,从不同源来的则被添加到不同队列。
  • setTimeout/Promise等API便是任务源,而进入任务队列的是他们指定的具体执行任务。

<img src="./images/task.png" style="width:500px"/>

宏任务
微任务

微任务和宏任务皆为异步任务,主要区别在于他们的执行顺序,Event Loop的走向和取值。

运行机制

在事件循环(Event Loop)中,每进行一次循环操作成为tick,每一次tick的任务处理模型是比较复制的,但关键步骤如下:

<img src="/images/执行机制.jpg" style="width:300px;"/>

3、 闭包

有权访问另外一个函数作用域中的变量的函数

用途
缺陷
4、异步执行
5、数据类型

主要要点:

6、原型链

<img src="/images/原型链.png" style="width:500px;"/>

实例、构造函数、原型对象

instanceof
New运算符

new做了什么?

  1. 创建了一个全新的对象。
  2. 这个对象会被执行[[Prototype]](也就是__proto__)链接。
  3. 生成的新对象会绑定到函数调用的this
  4. 通过new创建的每个对象将最终被[[Prototype]]链接到这个函数的prototype对象上。
  5. 如果函数没有返回对象类型Object(包含Functoin, Array, Date, RegExg, Error),那么new表达式中的函数调用会自动返回这个新的对象。
function Func(name){this.name = name};
var o1 = new Func('name1')
//模拟new
function new2(func,...param){
   /*
    //Object.create的作用
    function F(){}
    F.prototype = func.prototype
    var o =new F()
   */
    var o = Object.create(func.prototype)
    var ret = func.apply(o,param)
    return ret instanceof Object ? ret : o; //构造函数return了内容可以这样
}
var o2 = new2(Func,'name2')
7、this
8、继承
  1. 借助原型链实现继承

    /*
    缺点:
    1.父类中的属性(也就是父类this上的属性)是子类共用
    2.子类实例时无法向父类传参(因为父类早已实例化)
    */
    function P(){}
    function C(){}
    C.prototype = new P()
    
  2. 构造函数实现继承

    /*
    缺点:
    1.子类无法继承父类的prototype
    2.若父类方法绑定在this上则每个子类都会copy一份,违背代码复用
    */
    function P(){}
    P.prototype.say = function(){}//子类无法继承
    function C(){ P.call(this,arguments) } //继承父类属性
    
  3. 组合式继承

    /*
    缺点
    1.父类构造函数调用两次
    */
    function P(){}
    function C(){ P.call(this,arguments) } //P执行了1次
    C.prototype = new P() // P执行了2次
    
  4. 寄生组合继承

    function P(){}
    function C(){ P.call(this,arguments) }
    //实现方式
    C.prototype = Object.create(P.prototype) //通过浅拷贝继承父类方法,不需要调用一次父类构造函数
    C.prototype.constructor = C // 上一行代码对子类原型进行了拷贝,因此子类的constructor属性被重写,所以需要这样修复
    
  5. extends继承

    class P(){}
    class C extends P(){
      constructor(){
        super() //获得this对象
      }
    }
    
ES5的继承 vs ES6的继承

ES5

ES6

9、Promise
10、Ajax
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function(){
    if(xhr.readyState === 4){
        if(xhr.status===200||
           xhr.status===304||
           xhr.status===206){//媒体资源体积大,分步传输,状态码为206
            res = xhr.responseText
            if(typeof res==='string'){
                res = JSON.parse(res)
                console.log(res)
            }else{
                console.log(res)
            }
        }else{
            console.log(new Error(res))
        }
    }
}
xhr.open('GET','url',true)
xhr.send()
/*
xhr.open('POST','url',true)
xhr.setRequestHeader('content-type','application/json;charset=UTF-8')
xhr.send(JSON.stringify({}))
*/
readState

0-(未初始化)还没有调用send方法
1-(载入)已调用send()方法,正在发生请求
2-(载入完成)send方法执行完成,已经接收到前部响应内容
3-(交互)正在解析响应内容
4-(完成)响应内容解析完成,可以在客户端调用了

status

2xx - 表示成功处理请求,如200
3xx - 需要重定向,浏览器直接跳转
4xx - 客户端请求错误,如404
5xx - 服务器端错误

11、跨域

同源策略:非同源(域名、协议、端口)的脚本不能访问或者操作其它域的页面对象。

由于同源策略,非同源之间需要通讯,所以就需要跨域访问。

跨域,是指浏览器不能执行其他网站的脚本。它是由浏览器的同源策略造成的,是浏览器对JavaScript实施的安全限制。

同源策略限制了一下行为:

跨域通讯
12、优化
页面加载资源优化
JavaScript执行优化
雅虎军规

网页内容

服务器

cookie

CSS

JavaScript

图片

ETags:是服务器和浏览器用来决定浏览器缓存中组件与源服务器中的组件是否匹配的一种机制(“实体”也就是组件:图片,脚本,样式表等等)。添加ETags可以提供一种实体验证机制,比最后修改日期更加灵活。一个ETag是一个字符串,作为一个组件某一具体版本的唯一标识符。唯一的格式约束是字符串必须用引号括起来,源服务器用相应头中的ETag来指定组件的ETag。

然后,如果浏览器必须验证一个组件,它用If-None-Match请求头来把ETag传回源服务器。如果ETags匹配成功,会返回一个304状态码,这样就减少了12195个字节的响应体。Etag 通过文件版本标识,方便服务器判断请求的内容是否有更新,如果没有就响应 304,避免重新下载。

13、事件绑定
种类
事件模型
事件流
事件绑定

addEventListener(event,function,useCapture)

event:事件类型

function:执行函数

useCapture:可选;true:捕获阶段执行;false(默认):冒泡阶段执行

常用对象
event.preventDefault() //阻止默认事件
event.stopPropagation() //阻止冒泡
event.stoplmmediatePropagation() //阻止其它事件的响应(当注册了多个事件时)
event.currentTarget //其监听器触发事件的节点(绑定事件的元素),即当前处理该事件的元素、文档或窗口。
event.target //当前被点击的元素(旧版本的ie是sourceElement)
自定义事件
14、本地存储
  1. cookie

    • 4kb(不同浏览器存放大小不一样,一般为4kb)

    • 不同浏览器存放位置(磁盘)不一样

    • http请求会带上

    • 字符串形式存在

    • 仅以域名区分(不同协议、端口、子域可共享)

    • 可设过期时间,默认是会话结束则销毁

    • document.cookie = "username=cfangxu; domain=qq.com; path=/" // 添加cookie,设置生效子域及路径
      
  2. sessionStorage

    • 同源策略限制
    • 本质是读取字符串,存储过多会消耗内存,页面变卡
    • 一般为5M
    • 非IE可本地打开,IE需要在服务器中打开
    • 通过跳转打开新页面会复制源页面当前会话的sessionStorage
    • 会话结束时删除
  1. localStorage

    • 同源策略限制
    • 本质是读取字符串,存储过多会消耗内存,页面变卡
    • 一般为5M
    • 非IE可本地打开,IE需要在服务器中打开
    • 修改时会触发其它页面storage事件
    • 同一域中共享
    • 持久化本地存储,需要主动删除,不会过期
15、安全
Cross-site requset forgery(CSRF,跨站请求伪造)
Cross Site Script(XSS,跨站脚本工具)
16、函数式编程
17、Set、WeakSet、Map、WeakMap

18、布尔类型转换

数据类型 转换成true的取值 转换成false的取值
Undefined undefined
Boolean true false
Object 非null时都为true null
Number 任何非零数字值(包括无穷大) 0和NaN
String 非空字符串 ""(空字符串)

19、位运算符

&与,|或,~取反,^异或,>>左移,<<右移。

20、ES5的类 vs ES6 class

  1. 提升
    • class声明会提升,但不会初始化赋值。Foo进入暂时性死区,类似let、const声明变量
    • es5的函数会进行函数提升
  2. class声明内部会启动严格模式
  3. class的所有方法(包括静态方法和实例方法)都是不可枚举
  4. class 的所有方法(包括静态方法和实例方法)都没有原型对象 prototype,所以也没有[[construct]],不能使用 new 来调用
  5. 必须使用 new 调用 class
  6. class 内部无法重写类名。
  7. 继承
    • ES5是通过call或者apply回调方法调用父类
    • ES6的继承实现在于使用super关键字调用父类

21、async/await

async本身是promise+generator的语法糖。所以await后面的代码是miscrotask。

22、异步编程

  1. 回调函数
  2. 事件监听
  3. Promise对象
  4. Generator
  5. async/await

23、call & apply

作用一样,区别在于传参的不同

实现bind、call、apply
Function.prototype.myBind = function(ctx,...arg1){
    var fn = this
    return function(...arg2){
        return fn.call(ctx,...arg1,...arg2);
    }

}
Function.prototype.myCall = function(ctx,...args){
    const fn = Symbol('fn');
    ctx[fn] = this
    const result = ctx[fn](...args)
    Reflect.deleteProperty(ctx,fn);
    return result
}
Function.prototype.myApply = function(ctx,args){
    const fn = Symbol('fn');
    ctx[fn] = this
    const result = ctx[fn](...args)
    Reflect.deleteProperty(ctx,fn);
    return result
}

24、箭头函数

25、判断浏览器

function myBrowser() {
  var userAgent = navigator.userAgent; //取得浏览器的userAgent字符串  
  var isOpera = userAgent.indexOf("Opera") > -1;
  if (isOpera) {
    return "Opera"
  }; //判断是否Opera浏览器  
  if (userAgent.indexOf("Firefox") > -1) {
    return "Firefox";
  }  //判断是否Firefox浏览器  
  if (userAgent.indexOf("Chrome") > -1) {
    return "Chrome";
  }   //判断是否Google浏览器  
  if (userAgent.indexOf("Safari") > -1) {
    return "Safari";
  } //判断是否Safari浏览器  
  if (userAgent.indexOf("compatible") > -1 && userAgent.indexOf("MSIE") > -1 && !isOpera) {
    return "IE";
  }; //判断是否IE浏览器  
}

26、垃圾回收机制

没有被引用的对象就是垃圾,要被清除。几个对象引用形成一个环,相互引用,但是访问不到的,也是垃圾。

27、块级作用域与函数声明

// 浏览器的 ES6 环境
function f() { console.log('I am outside!'); }

(function () {
  if (false) {
    // 重复声明一次函数f
    function f() { console.log('I am inside!'); }
  }

  f();
}());
// Uncaught TypeError: f is not a function

为了兼容旧代码,浏览器的实习可以不遵守规定(块级作用域之中,函数声明语句的行为类似于let,在块级作用域之外不可引用):

相当于如下:

 浏览器的 ES6 环境
function f() { console.log('I am outside!'); }
(function () {
  var f = undefined;
  if (false) {
    function f() { console.log('I am inside!'); }
  }

  f();
}());
// Uncaught TypeError: f is not a function
28、表示一个字符的方式(6种)
'\z' === 'z'  // true
'\172' === 'z' // true
'\x7A' === 'z' // true
'\u007A' === 'z' // true
'\u{7A}' === 'z' // true
上一篇 下一篇

猜你喜欢

热点阅读