前端基础知识整理汇总(上)

前端基础知识整理汇总(上)

HTML页面的生命周期

HTML页面的生命周期有以下三个重要事件:

1、DOMContentLoaded —— 浏览器已经完全加载了 HTML,DOM 树已经构建完毕,但是像是 和样式表等外部资源可能并没有下载完毕。
2、load —— 浏览器已经加载了所有的资源(图像,样式表等)。
3、beforeunload —— 当用户即将离开当前页面(刷新或关闭)时触发。正要去服务器读取新的页面时调用,此时还没开始读取;
4、unload —— 在用户离开页面后触发。从服务器上读到了需要加载的新的页面,在即将替换掉当前页面时调用。

每个事件都有特定的用途:

1、DOMContentLoaded —— DOM 加载完毕,所以 JS 可以访问所有 DOM 节点,初始化界面。
2、load —— 附加资源已经加载完毕,可以在此事件触发时获得图像的大小(如果没有被在 HTML/CSS 中指定)
3、beforeunload —— 该事件可用于弹出对话框,提示用户是继续浏览页面还是离开当前页面。
4、unload —— 删除本地数据localstorage等

DOMContentLoaded

DOMContentLoaded 由 document 对象触发。使用 addEventListener 来监听它:

document.addEventListener("DOMContentLoaded", () => {
   });

DOMContentLoaded 和脚本

当浏览器在解析 HTML 页面时遇到了 标签,将无法继续构建DOM树(UI 渲染线程与 JS 引擎是互斥的,当 JS 引擎执行时 UI 线程会被挂起),必须立即执行脚本。所以 DOMContentLoaded 有可能在所有脚本执行完毕后触发。

外部脚本(带 src 的)的加载和解析也会暂停DOM树构建,所以 DOMContentLoaded 也会等待外部脚本。带 async 的外部脚本,可能会在DOMContentLoaded事件之前或之后执行。带 defer 的脚本肯定会在在DOMContentLoaded事件之前执行。

DOMContentLoaded 与样式表

外部样式表并不会阻塞 DOM 的解析,所以 DOMContentLoaded 并不会被它们影响。

load

window 对象上的 load 事件在所有文件包括样式表,图片和其他资源下载完毕后触发。

window.addEventListener('load', function(e) {
   ...});

window.onload = function(e) {
    ... };

beforeunload

当窗口即将被卸载(关闭)时, 会触发该事件。此时页面文档依然可见, 且该事件的默认动作可以被取消。beforeunload在unload之前执行,它还可以阻止unload的执行。

// 推荐使用
window.addEventListener('beforeunload', (event) => {
   
  // Cancel the event as stated by the standard.
  event.preventDefault();
  // Chrome requires returnValue to be set.
  event.returnValue = '关闭提示';
});


window.onbeforeunload = function (e) {
   
  e = e || window.event;
  // 兼容IE8和Firefox 4之前的版本
  if (e) {
   
    e.returnValue = '关闭提示';
  }
  // Chrome, Safari, Firefox 4+, Opera 12+ , IE 9+
  return '关闭提示';
};

unload

用户离开页面的时候,window 对象上的 unload 事件会被触发,无法阻止用户转移到另一个页面上。

// 推荐使用
window.addEventListener("unload", function(event) {
    ... });

window.onunload = function(event) {
    ... };

readyState

document.readyState 表示页面的加载状态,有三个值:

loading 加载 —— document仍在加载。

interactive 互动 —— 文档已经完成加载,文档已被解析,但是诸如图像,样式表和框架之类的子资源仍在加载。

complete —— 文档和所有子资源已完成加载。 load 事件即将被触发。
可以在 readystatechange 中追踪页面的变化状态:

document.addEventListener('readystatechange', () => {
   
  console.log(document.readyState);
});

Script标签:向HTML插入JS的方法

没有 defer 或 async,所有

使用

1.页面中嵌入script代码, 只需指定type属性

<script type="text/javascript">
  function sayHi() {
   
    console.log('hihihi');
    // 内部不能出现'</script>'字符串,如果必须出现,必须使用转义标签‘\’
    alert('<\/script>');
  }
</script>

包含在

2.包含外部js文件, src属性是必须的。

<script src="example.js"></script>
// 带有src属性的元素不应该在标签之间包含额外的js代码,即使包含,只会下载并执行外部文件,内部代码也会被忽略。

与嵌入式js代码一样, 在解析外部js文件时,页面的处理会暂时停止。

改变脚本行为的方法

1. defer: 立即下载,延迟执行

加载和渲染后续文档元素的过程将和脚本的加载并行进行(异步),但是脚本的执行会在所有元素解析完成之后。脚本总会按照声明顺序执行。

在DOMContentLoaded事件之前执行。

<script defer="defer" src="example.js"></script>

2. async: 异步脚本

加载和渲染后续文档元素的过程将和脚本的加载与执行并行进行(异步)。但是async 在下载完毕后的执行会阻塞HTML的解析。脚本加载后马上执行,不能保证异步脚本按照他们在页面中出现的顺序执行。
一定会在load事件之前执行,可能会在DOMContentLoaded事件之前或之后执行。

<script async="async" src="example.js"></script>

区别:

图片

meta

META标签是HTML标记HEAD区的一个关键标签,它提供的信息虽然用户不可见,但却是文档的最基本的元信息。除了提供文档字符集、使用语言、作者等网页相关信息外,还可以设置信息给搜索引擎,目的是为了SEO(搜索引擎优化)。

HTML 元素表示那些不能由其它 HTML 元相关(meta-related)元素((、,

属性
name

设置元数据的名称。name 和 content 属性可以一起使用,以名-值对的方式给文档提供元数据,content 作为元数据的值。

content

设置与 http-equiv 或 name 属性相关的元信息。

charset

声明了文档的字符编码。如果使用了这个属性,其值必须是与ASCII大小写无关(ASCII case-insensitive)的"utf-8"。

http-equiv

定义了一个编译指示指令,其作用类似于http协议, 告诉浏览器一些关于字符设定,页面刷新,cookie,缓存等等相关信息。属性名叫做 http-equiv 是因为所有允许的值都是HTTP头部的名称。可设置的值有:

1、content-security-policy:它允许页面作者定义当前页的内容策略。内容策略主要指定允许的服务器源和脚本端点,这有助于防止跨站点脚本攻击。

2、Expires:可以用于设定网页的到期时间,一旦过期则必须到服务器上重新调用。content必须使用GMT时间格式;

3、content-type:如果使用这个属性,其值必须是"text/html; charset=utf-8"。注意:该属性只能用于 MIME type为 text/html 的文档,不能用于MIME类型为XML的文档。

4、default-style:设置默认CSS 样式表组的名称。

5、refresh:定时让网页在指定的时间n内,刷新或跳转;
如果 content 只包含一个正整数,则是n秒后, 页面刷新。
如果 content 包含一个正整数,并且后面跟着字符串 ‘;url=’ 和一个合法的 URL,则是重定向到指定链接的时间间隔(秒)。

meta 元素定义的元数据的类型包括以下几种:

1、如果设置了 name 属性,meta 元素提供的是文档级别(document-level)的元数据,应用于整个页面。
2、如果设置了 http-equiv 属性,meta 元素则是编译指令,提供的信息与类似命名的HTTP头部相同。
3、如果设置了 charset 属性,meta 元素是一个字符集声明,告诉文档使用哪种字符编码。
4、如果设置了 itemprop 属性,meta 元素提供用户定义的元数据。

注意: 全局属性 name 在 元素中具有特殊的语义;另外, 在同一个 标签中,name, http-equiv 或者 charset 三者中任何一个属性存在时,itemprop 属性不能被使用。

使用
content值里有多个属性通过,隔开,同时设置多个属性。

/* name */
// 适配移动设备
<meta name="viewport" content="width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no" />
// 检测html格式:禁止把数字转化为拨号链接
<meta name="format-detection" content="telephone=no" /> 

/* charset */
<meta charset="utf-8">

/* http-equiv */
<meta http-equiv="refresh" content="3;url=https://www.mozilla.org">
<meta http-equiv="Expires" content="Mon,12 May 2001 00:20:00 GMT">
meta viewport元信息

什么是 viewport?

viewport 是浏览器的可视区域,可视区域的大小是浏览器自己设置的。它可能大于移动设备可视区域,也可能小于移动设备可视区域。一般来讲,移动设备上的viewport都是大于移动设备可视区域。在控制台输出window.innerWidth查看Viewport大小。

相关概念

设备像素: 设备屏幕分辨率。iphone6p 的分辨率是 1334750;
设备独立像素: 设备上程序用来描绘数据的一个个的“点”, 在控制台用 screen.width/height查看。iphone6p 的设备独立像素是375
667;
设备像素比(DPR): 设备像素(宽)/设备独立像素(宽),DPR越高渲染越精致。在控制台输出window.devicePixelRatio查看设备像素比。iphone6s 的设备像素比就是 750 / 375 = 2;
CSS像素: 浏览器使用的单位,用来精确度量网页上的内容。在一般情况下(页面缩放比为 1),1 个 CSS 像素等于 1 个设备独立像素。
屏幕尺寸: 屏幕对角线的长度,以英尺为单位。
像素密度(PPI): 每英寸屏幕拥有的像素数。

为什么要使用meta viewport?
通常情况下,移动设备上的浏览器都会把viewport设为980px或1024px,此时页面会出现横向滚动条,因为移动设备可视区域宽度是比这个默认的viewport的宽度要小。所以出现了meta 标签设置viewport 元始性进行移动端网页优化。

meta viewport 属性

width: 控制 viewport 的大小,可以给它指定一个值(正整数),或者是一个特殊的值(如:device-width 设备独立像素宽度,单位缩放为 1 时);
initial-scale: 初始缩放比例,即当页面第一次加载时的缩放比例,为一个数字(可以带小数);
maximum-scale: 允许用户缩放到的最大比例,为一个数字(可以带小数);
minimum-scale: 允许用户缩放到的最小比例,为一个数字(可以带小数);
user-scalable: 是否允许用户手动缩放,值为 “no”(不允许) 或 “yes”(允许);
height: 与 width 相对应(很少使用)。

基本类型和引用类型

基本类型

基本类型:undefined、null、string、number、boolean、symbol

特点
1.基本类型的值是不可变得

// 任何方法都无法改变一个基本类型的值
 let name = 'jay';
 name.toUpperCase(); // 输出 'JAY'
 console.log(name); // 输出  'jay'

2.基本类型的比较是值的比较

// 只有在它们的值相等的时候它们才相等
let a = 1;
let b = true;
console.log(a == b); //true
// 用==比较两个不同类型的变量时会进行一些类型转换。
// 先会把true转换为数字1再和数字1进行比较,结果就是true了

3.基本类型的变量是存放在栈区的(栈区指内存里的栈内存)

引用类型

引用类型:Object、Array、RegExp、Date、Function等
引用类型也可以说是对象。对象是属性和方法的集合,也就是说引用类型可以拥有属性和方法,属性又可以包含基本类型和引用类型。
特点
1.引用类型的值是可变的

// 我们可为为引用类型添加属性和方法,也可以删除其属性和方法
let person = {
    name: 'pig' };
person.age = 22;
person.sayName = () => console.log(person.name); 
person.sayName(); // 'pig'
delete person.name;

2.引用类型的比较是引用的比较

let person1 = '{}';
let person2 = '{}';
console.log(person1 == person2); // 字符串值相同,true

let person1 = {
   };
let person2 = {
   };
console.log(person1 == person2); // 两个对象的堆内存中的地址不同,false

3.引用类型的值是同时保存在栈内存和堆内存中的对象
javascript和其他语言不同,其不允许直接访问内存中的位置,也就是说不能直接操作对象的内存空间。

实际上,是操作对象的引用,所以引用类型的值是按引用访问的。准确地说,引用类型的存储需要内存的栈区和堆区(堆区是指内存里的堆内存)共同完成,栈区内存保存变量标识符和指向堆内存中该对象的指针,也可以说是该对象在堆内存的地址。

作用域和执行上下文

JavaScript代码的整个执行过程,分为两个阶段,代码编译阶段与代码执行阶段。

1、编译阶段:由编译器完成,将代码翻译成可执行代码。这个阶段作用域规则会确定。
2、执行阶段:由引擎完成,主要任务是执行可执行代码。执行上下文在这个阶段创建。

作用域

简单来说作用域就是一个区域,没有变量。作用域可以嵌套。作用域规定了如何查找变量,也就是确定当前执行代码对变量的访问权限。作用域在函数定义时就已经确定了,不是在函数调用确定。

ES6 之前 JavaScript 只有全局作用域和函数作用域。 ES6 后,增加了块级作用域(最近大括号的作用范围), 通过let 和 const 声明的变量。

作用域其实由两部分组成:

1、记录作用域内变量信息(假设变量,常量,函数等统称为变量)和代码结构信息的东西,称之为 Environment Record。
2、一个引用 outer,这个引用指向当前作用域的父作用域。全局作用域的 outer 为 null。

词法作用域

JavaScript 采用词法作用域(lexical scoping),也就是静态作用域。

所谓词法(代码)作用域,就是代码在编写过程中体现出来的作用范围,代码一旦写好了,没有运行之前(不用执行),作用范围就已经确定好了,这个就是所谓的词法作用域。

词法作用域的规则:

1、函数允许访问函数外部的数据
2、整个代码结构中只有函数才能限定作用域
3、作用规则首先使用变量提升规则分析
4、如果当前作用规则里面有该名字,则不考虑外面的外面的名字

var a = 1;
function out() {
   
  var a = 2;
  inner();
}

function inner() {
   
  console.log(a)
}
out();  //====>  1
作用域链

当查找变量的时候,会先从当前上下文的变量对象中查找,如果没有找到,就会从父级(词法层面上的父级)执行上下文的变量对象中查找,一直找到全局上下文的变量对象,也就是全局对象。这样由多个执行上下文的变量对象构成的指针链表就叫做作用域链。

作用域链本质上是一个指向当前环境与上层环境的一系列变量对象的指针列表(它只引用但不实际包含变量对象),作用域链保证了当前执行环境对符合访问权限的变量和函数的有序访问。

例子:
用一个数组scopeChain来表示作用域链,数组的第一项scopeChain[0]为作用域链的最前端,而数组的最后一项,为作用域链的最末端,所有的最末端都为全局变量对象。

var a = 1;             
function out() {
   
    var b = 2;
    function inner() {
   
        var c = 3;
        console.log(a + b + c);
    }
    inner();          
}
out();

首先,代码开始运行时就创建了全局上下文环境,接着运行到out()时创建** out函数的执行上下文,**最后运行到inner()时创建 inner函数的执行上下文, 我们设定他们的变量对象分别为VO(global),VO(out), VO(inner)。

当函数创建时,执行上下文为:

// 全局上下文环境
globalEC = {
   
  VO: {
   
    out: <out reference>,  // 表示 out 的地址引用
    a: undefined
  },
  scopeChain: [VO(global)], // 作用域链
}

// out 函数的执行上下文
outEC = {
   
  VO: {
   
    arguments: {
   ...},
    inner: <inner reference>,  // 表示 inner 的地址引用
    b: undefined
  },
  scopeChain: [VO(out), VO(global)], // 作用域链
}

// inner 函数的执行上下文
innerEC = {
   
  VO: {
   
    arguments: {
   ...},  
    c: undefined,
  }, 
  scopeChain: [VO(inner), VO(out), VO(global)], // 作用域链
}
执行上下文

简单来说,当在代码执行阶段执行到一个函数的时候,就会进行准备工作,这里的“准备工作”,就叫做"执行上下文(EC)",也叫执行上下文环境,也叫执行环境。js引擎创建了执行上下文栈(Execution context stack,ECS)来管理执行上下文。

当调用一个函数时,一个新的执行上下文就会被创建。而一个执行上下文的生命周期可以分为两个阶段:

创建阶段:在这个阶段,执行上下文会分别创建变量对象,建立作用域链,以及确定this的指向。
代码执行阶段:开始执行代码,会完成变量赋值,函数引用,以及执行其他代码。
特点

1、处于活动状态的执行上下文环境只有一个, 只有栈顶的上下文处于活动状态,执行其中的代码。
2、函数每调用一次,都会产生一个新的执行上下文环境。
3、全局上下文在代码开始执行时就创建,只有唯一的一个,永远在栈底,浏览器窗口关闭时出栈。
4、函数被调用的时候创建上下文环境。

变量对象
变量对象的创建过程

1、建立arguments对象。检查当前上下文中的参数,建立该对象下的属性与属性值。

2、检查当前上下文的函数声明,也就是使用function关键字声明的函数。在变量对象中以函数名建立一个属性,属性值为指向该函数所在内存地址的引用。如果函数名的属性已经存在,那么该属性将会被新的引用所覆盖。

3、检查当前上下文中的变量声明,每找到一个变量声明,就在变量对象中以变量名建立一个属性,属性值为undefined。如果该变量名的属性已经存在,为了防止同名的函数被修改为undefined,则会直接跳过,原属性值不会被修改。

活动对象

变量对象与活动对象其实都是同一个对象,只是处于执行上下文的不同生命周期。不过只有处于函数调用栈栈顶的执行上下文中的变量对象,才会变成活动对象。

执行上下文栈

执行上下文可以理解为当前代码的执行环境,JavaScript中的运行环境大概包括三种情况:

全局环境: JavaScript代码运行起来会首先进入该环境
函数环境: 当函数被调用执行时,会进入当前函数中执行代码
eval
在代码开始执行时,首先会产生一个**全局执行上下文环境,调用函数时,会产生函数执行上下文环境,**函数调用完成后,它的执行上下文环境以及其中的数据都会被销毁,重新回到全局执行环境,网页关闭后全局执行环境也会销毁。其实这是一个压栈出栈的过程,全局上下文环境永远在栈底,而当前正在执行的函数上下文在栈顶。

var a = 1;             // 1.进入全局上下文环境
function out() {
   
    var b = 2
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值