当前位置:   article > 正文

前端js基础知识_前端js基础知识点总结

前端js基础知识点总结

1. 作用域

作用域就是一个变量可以使用的范围,主要分为全局作用域和函数作用域和块级作用域(es6新增

全局作用域:Js中最外层的作用域

函数作用域:js通过函数创建的一个独立作用域,函数可以嵌套,所以作用域也可以嵌套

块级作用域:Es6中新增,由大括号包裹,比如:if(){}, for(){} function等

2. 自由变量与作用域链

自由变量:在当前作用域被使用,但是没有被定义的变量,被称作自由变量

作用域链:一个变量在当前作用域没有定义,但是被使用了,就会向上级作用域,一层一层依次查找,直至找到为止,如果全局作用域都没有找到这个变量就会报错。这个自由变量查找的过程就是作用域链

注意:函数中的自由变量取决于函数定义的位置,与执行的位置无关。

3. 变量的提升(预解析)

js在运行之前,会把所有带有var或function的变量与函数提升至当前作用域的最上方

var只提升变量,不提升赋值,而function提升整个函数体

注意:function的优先级比var要高

4. 闭包

函数中套了一个函数,内层函数可以访问外层函数中的变量

闭包的分类

1 函数做为参数被传递

2 函数做为返回值被返出

闭包的运用场景

1 封装对象的私有属性和方法,用于隐藏数据,做一个简单的缓存工具

2 做为回调函数使用

3 利用闭包实现函数的防抖,节流

   防抖:例如一个倒计时,被连续点击时,关闭上一个倒计时,重新开启一个新的倒计时

   节流:例如一个倒计时,被连续点击时,规定时间内,无论点击多少次,只触发一次

优点:闭包因为长期驻扎在内存中。可以重复使用变量,不会造成变量污染

缺点:闭包会使函数中的变量都被保存在内存中,内存消耗很大,滥用闭包,会造成网页的性能问题,可能会导致内存泄露

解决方法:在退出函数之前,将不使用的变量全部删除

5. this指向

this指向什么值,是在执行的时候确定的,与定义的位置无关,箭头函数除外

常用的调用场景

普通函数指向当前调用它的对象(默认为window)
构造函数与class类指向当前的实例化对象
对象方法的调用指向调用该方法的对象
箭头函数指向函数声明所在的对象,与其他的不同,其他的是在调用时,箭头函数则是在声明时
定时器(特殊例子)指向window(默认), 但是如果内部函数为箭头函数,则指向箭头函数声明时坐在的对象

总结:

  • 普通函数中调用,this指向window
  • 对象方法中调用,this指向当前对象
  • call apply bind中调用, this指向被传入的对象
  • class中的方法中调用, this指向实例对象
  • 箭头函数,this就是父级上下文中的this 

修改this指向

call

多个参数,

第一个参数就是要修改的this指向,其他参数是以散落的形式给调用该方法的函数传递参数

Game.call(this , '王者荣耀', '手游')

apply

两个参数

第一个参数就是要修改的this指向,第二个参数是以数组的形式给调用该方法的函数传递参数
Game.apply(this, ['王者荣耀', '手游'])

bind

一个参数,就是要修改的this指向

返回值是调用该方法的函数本身 函数需要再次调用才会执行,传递参数可以在函数调用时传递
 Game.bind(this)('王者荣耀', '手游')

垃圾回收机制与内存泄漏

垃圾回收机制

浏览器的js具有自动垃圾回收机制(GC),执行环境会管理代码在执行中所使用的内存,垃圾回收器会定期寻找不再使用的变量,释放其内存,垃圾回收器会按照时间间隔周期性的执行。

变量的死亡

全局作用域内的变量,会在关闭浏览器关闭页面时结束,被垃圾回收期回收

函数级与块级作用域内的变量,只有在函数执行的过程中存在,函数执行完毕,垃圾回收器回收释放

闭包内,因为内部函数使用外部函数变量的原因,它内部的变量,永远不会结束、

判别变量是否还有用的两种方式:

1. 标记清除(常用)

垃圾回收器在运行的时候会给存储在内存中的所有变量都加上标记。当一个变量进入环境时,就将这个变量标记为“进入环境”,而当变量离开环境时,则将其标记为“离开环境”。垃圾收集器下次运行时,就会把所有标为离开环境的变量回收释放。

  1. function test(){
  2. var a = 10 ;
  3. var b = 20 ;
  4. }
  5. // 在调用该函数时,内部的变量会标记为进入环境
  6. test();
  7. // 函数执行完毕之后 a、b又被标离开环境,被回收。

2. 引用计数

跟踪记录每个值别引用的次数,当声明了一个变量,并将一个引用类型的值赋给该变量时,那这个值的引用次数就是1,而这个值再被赋值给另一个变量,那这个值的引用次数+1,相反,如果包含这个值的变量,获取了另外的值,那这个值的引用次数-1,当这个值的引用次数为0时,垃圾回收器下次运行时,就会把这个值回收释放。

  1. function test() {
  2. var a = {}; // a指向对象的引用次数为1
  3. var b = a; // a指向对象的引用次数加1,为2
  4. var c = a; // a指向对象的引用次数再加1,为3
  5. var b = {}; // a指向对象的引用次数减1,为2
  6. }

内存泄漏

1. 循环引用
一个DOM对象被一个Javascript对象引用,又引用同一个或其它的Javascript对象,这个DOM对象可能会引发内存泄露。将不会在脚本停止的时候被垃圾回收器回收。要想破坏循环引用,赋值为null即可

2. 闭包

在闭包中引入闭包外部的变量时,当闭包结束时此对象无法被垃圾回收

3. DOM泄露

当原有的DOM被移除时,子结点引用没有被移除则无法回收

宏任务与微任务

js的机制是先执行同步事件,再执行异步事件

异步事件又分为了宏任务与微任务,微任务的执行时间要比宏任务早

宏任务:setTimeout setInterval Ajax DOM事件

微任务:promise   async/await

异步与单线程

异步和单线程是相辅相成的,js是一门单线程脚本语言,所以需要异步来辅助

异步与同步的区别

同步会阻塞代码的执行,而异步不会

JS的任务运行顺序

1 将所有的任务放进执行线

2 分出同步任务还是异步任务

3 将同步任务放入主线程,进行执行

4 将异步任务放入Event Table并注册函数,放入事件队列中

5 在同步任务完成后,再将任务队列的放入主线程进行执行

6 异步先执行微任务,再执行宏任务

注意事项

1 在异步事件中,遇到其他宏任务,将其放进下一个事件队列

2 swite异步代码同步执行,但是会把后面的代码,变成一个微任务

数据类型

基本数据类型(值类型): Number、String、Boolean、Undefined、Null、Symbol(es6新增独一无二的值) 和 BigInt(es10新增);

引用数据类型: Object。包含Object、Array、 function、Date、RegExp。

四种方法可以判断数据类型

typeof、instanceof、constructor、Object.prototype.toString.call()、jquery.type()

for···in和for···of的区别
①从遍历数组角度来说,for···in遍历出来的是key(即下标),for···of遍历出来的是value(即数组的值);

②从遍历字符串的角度来说,同数组一样。
③从遍历对象的角度来说,for···in会遍历出来的为对象的key,但for···of会直接报错。

④如果要使用for…of遍历普通对象,需要配合Object.keys()一起使用。

null和undefined区别
在 if 语句中 null 和 undefined 都会转为false两者用相等运算符比较也是相等

1.null表示没有对象,可能将来要赋值一个对象,即该处不应该有值

1 作为函数的参数,表示该函数的参数不是对象

2 作为对象原型链的终点

2 undefined表示缺少值,即此处应该有值,但没有定义

1 定义了形参,没有传实参,显示undefined

2 对象属性名不存在时,显示undefined

3 函数没有写返回值,即没有写return,拿到的是undefined

4 写了return,但没有赋值,拿到的是undefined

设计模式
一、单例模式

1. 定义

保证一个类仅有一个实例,并提供一个访问它的全局访问点

2. 核心

确保只有一个实例,并提供全局访问

3. 实现

在vue脚手架项目开发中,我们需要对axios进行请求拦截,响应拦截,多次调用封装好的axios实例也仅设置一次,封装后的axios就是要一个单例

二、发布者、订阅者模式

vue.js 则是采用数据劫持结合发布者-订阅者模式的方式,通过Object.defineProperty()来劫持各个属性的setter,getter,在数据变动时发布消息给订阅者,触发相应的监听回调。


 

js的事件
DOM事件的三种级别
 DOM 0级事件

DOM 0级时间分两种,一是直接在标签内直接添加执行语句,二是定义执行函数

    <input type="text" id="test">
    <input type="button"    value="button"    οnclick="alert(document.getElementById('test').value)">
 
    <script>
        document.getElementById('button').οnclick=function(){                                 
         alert(document.getElementById('test').value);
        }
    </script> 
DOM 2级事件

2级事件有3个参数,分别为 事件名称,执行函数,指定冒泡还是捕获,默认是false,冒泡。

element.addEventListener('click',function(){},false)
DOM 3级事件

同DOM2级一样,只不过添加了更多的事件类型,鼠标事件、键盘事件

element.addEventListener('keyup',function(){},false)
DOM的事件类型
事件类型分两种:事件捕获、事件冒泡。

事件捕获就是由外往内,从事件发生的顶点window开始,之后是document对象,逐级往下查找,一直到目标元素。

事件冒泡就是由内往外,从具体的目标节点元素触发,逐级向上传递,直到根节点window。

DOM事件的事件流(事件传播)
事件流就是,事件的传播过程。

DOM完整的事件流包括三个阶段:事件捕获阶段、目标阶段和事件冒泡阶段。

事件通过捕获到达目标元素,这个时候就是目标阶段。从目标节点元素将事件上传到根节点的过程就是第三个阶段,冒泡阶段

自定义事件
我们也可以通过 new Event()自定义事件

var eve = new Event('test'); //通过new Event 创建事件
    dom.addEventListener('test', function () { //注册事件
    console.log('test dispatch');
});
setTimeout(function () {
    dom.dispatchEvent(eve);  //触发事件
}, 1000);
解决跨域
什么是跨域

理解跨域的概念:协议、域名、端口都相同才同域,否则都是跨域

跨域就是指浏览器不允许当前页面的所在源,去请求另一个源的数据

JSONP原理        

出于安全考虑,服务器不允许 ajax 跨域获取数据,但是可以跨域获取文件内容,所以基于这一点,可以动态创建 script 标签,使用标签的 src 属性访问 js 文件的形式获取 js 脚本,并且这个 js 脚本中的内容是函数调用,该函数调用的参数是服务器返回的数据,为了获取这里的参数数据,需要事先在页面中定义回调函数,在回调函数中处理服务器返回的数据,这就是解决跨域问题的jsonp原理。

脚手架解决跨域

在脚手架中,创建 vue.congif.js 文件,里面的 devServer 是进行开发环境的服务器配置的,里面有proxy是用来进行代理的转发,在proxy里的 target 设置转发的网址

因为跨域的问题,axios是无法请求网址数据的,但是浏览器可以,所以,应用代理转发请求数据到我们设置的网址中,而axios请求该网址,相当于一个中间商进行了一次代理

let、var、const区别
Var是块级作用域,值可以更改,多次定义会被顶替,拥有变量提升特性,可以不赋值

Let 函数级作用域,值可以更改,不能多次定义,无法变量提升,可以不赋值

Const 函数级作用域,是一个常量,值不能为空,一经定义无法更改,无法变量提升,必须赋值

注意:const如果定义的是一个数组或者对象,它的值就是一个指针,数组或对象里面的值是可以更改的,并不影响这个指针


es6解构赋值
es6可以根据一定的规则,从数组或变量中提取值赋给变量,字符串也可以直接进行结构赋值,无论对象还是数组,两边的 = 数据类型和数据结构都必须保持一致

解构

数组的解构:数组的结构赋值是按照索引值一一对应的,如果多层嵌套,结构也必须保持一致,不想要的数据可以在解构时用,隔开 空格表示

字符串的解构遵循数组的方式,因为它同样有下标和length

对象的解构:对象的解构按照key值来对应 {key}

//数组结构
var a, b, rest;
[a, b] = [10, 20];
console.log(a); // 10
console.log(b); // 20
 
//对象解构
({ a, b } = { a: 10, b: 20 });
console.log(a); // 10
console.log(b); // 20
 
// ...rest 解构数组
[a, b, ...rest] = [10, 20, 30, 40, 50];
console.log(a); // 10
console.log(b); // 20
console.log(rest); // [30, 40, 50]
 
// ...rest 解构对象(最新)
({a, b, ...rest} = {a: 10, b: 20, c: 30, d: 40});
console.log(a); // 10
console.log(b); // 20
console.log(rest); // {c: 30, d: 40}
 
//解析一个从函数返回
function f() {
  return [1, 2];
}
 
var a, b; 
[a, b] = f(); 
console.log(a); // 1
console.log(b); // 2
 

解构的默认值

数组,对象,字符串都是一样的,默认值就是a = 值 ,默认值只有在没有数据,也就是undefined时生效

解构赋值的rest参数

rest会将剩余的所有数据赋值给rest,必须放在最后,...rest

箭头函数与普通函数的区别
普通函数会遇到this作用域问题,ES6新建箭头函数

箭头函数无法作为构造函数使用,无法实例化,

箭头函数this指向她所在的作用域,

箭头函数本身没有arguments参数

箭头函数不能通过call()、apply()、bind()方法直接修改它的this指向

箭头函数没有原型属性

promise使用及实现
promise是es6提出的一种异步编程的解决方案,接受两个函数做为参数,从语法上说,promise 是一个对象,从它可以获取异步操作的的最终状态(成功或失败),本质上是一个构造函数,

promise的状态

promise的状态不受外部影响,一经改变就代表执行结束,无法再进行更改        

pending 初始状态     fulfilled 成功状态    rejected 失败状态

promise的参数

resolve的作用是将promise的状态从进行中pending变为已完成fullfilled,并将成功信息返出

reject的作用是将promise的状态从进行中pending变为已失败rejected,并将失败信息返出

promise的状态一经改变就代表执行结束

promise一些api

.then()获取promise的结果

.catch()来获取失败时返出的错误信息

Promise.all( ) 接受多个promise的实例做为参数,参数必须是一个数组,promise都执行成功后,返回的是执行后的结果的一个数组,如果有一个失败了,返回的是第一个失败的返回值

Promise.race( ) 接受多个promise的实例做为参数,其中一个promise完成时执行,返回结果是第一个完成的promise的返回数据

名词约定

promise(首字母小写)对象指的是“Promise实例对象”

Promise首字母大写且单数形式,表示“Promise构造函数”

Promises首字母大写且复数形式,用于指代“Promises规范”

async/await
特点

asayc的用法,它作为一个关键字放到函数前面,这样普通函数就变为了异步函数
异步async函数调用,跟普通函数的使用方式一样
异步async函数返回一个promise对象
async函数配合await关键字使用,await异步代码同步执行,但是后面的代码将会被阻塞,变为一个异步微任务,
优点

1.方便级联调用:即调用依次发生的场景;

2.同步代码编写方式:更符合代码编写习惯;

3.多个参数传递: Promise的then函数只能传递一个参数,async/await没有这个限制,可以定义块级变量传递数据

4.同步代码和异步代码可以一起编写: async/await整个书写习惯都是同步的,不需要纠结同步和异步的区别,当然,异步过程需要包装成一个Promise对象放在await关键字后面;

5.sync/await是对Promise的优化:不过在写代码时,Promise本身的API出现得很少,很接近同步代码的写法;

Es6中新的数据类型symbol
Symbol 值通过Symbol函数生成。对象的属性名现在可以有两种类型,一种是原来就有的字符串,另一种就是新增的 Symbol

凡是属性名属于 Symbol 类型,就都是独一无二的,可以保证不会与其他属性名产生冲突。

注意,Symbol函数前不能使用new命令,否则会报错。这是因为生成的 Symbol 是一个原始类型的值,不是对象,所以不能添加属性。基本上,它是一种类似于字符串的数据类型。

当url输入到页面发生了什么
浏览器的地址栏输入URL并按下回车,

查找当前的URL是否存在缓存,并比较缓存是否过期,

DNS解析URL对应的IP,

根据IP建立TCP连接(三次握手),

HTTP发起请求,服务器处理请求,浏览器接收HTTP响应,

渲染页面,构建DOM树,

关闭TCP连接(四次挥手)。

三次握手和四次挥手
三次握手:

第一次:建立连接时,客户端发送一个SYN包到服务器请求链接

第二次:服务器收到SYN包,并确认,同时也发送一个SYN+ACK包到客户端

第三次:客户端收到服务器的SYN+ACK包,向服务器发送最终的确认ACK包,发送完毕,客户端和服务端连接成功,完成三次握手

四次挥手:

第一次:浏览器发送完数据后,发送断开连接的FIN请求

第二次:服务器发送ACK包到客户端,确认浏览器的断开请求,并做好准备

第三次:服务器最终向客户端确认是否断开连接

第四次:客户端确认,断开服务器

http和https的区别
1、HTTP是超文本传输协议,信息是明文传输,HTTPS是具有安全性的SSL加密传输协议。

2、HTTPS协议需要ca申请证书,一般免费证书少,因而需要一定费用。

3、HTTP和HTTPS使用的是完全不同的连接方式,用的端口也不一样。前者是80,后者是443。

4、HTTP连接是无状态的,HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,安全性高于HTTP协议。

使用基于token的登录流程
客户端使用用户名跟密码请求登录
服务端收到请求,去验证用户名与密码
验证成功后,服务端会签发一个 Token,再把这个 Token 发送给客户端
客户端收到 Token 以后可以把它存储起来,比如放在 Cookie 里或者 Local Storage 里
客户端每次向服务端请求资源的时候需要带着服务端签发的 Token
服务端收到请求,然后去验证客户端请求里面带着的 Token,如果验证成功,就向客户端返回请求的数据
Get和post
Get是向服务器请求数据,post是向服务器提交数据

Get在数据传输时可见,post不可见

Get传输数据量小,post比较大

Get执行效率却比Post方法好

Get是form提交的默认方法。

get推荐使用在查询信息时的使用,post适用于登录,注册等带有信息的请求

web安全及防护
1.XSS攻击原理:

攻击者往Web页面里插入恶意 html标签或者javascript代码。用来窃取cookie中的用户信息

解决:对一些输入的字符进行过滤,尽量采用post表单提交的方式。

2.CSRF攻击(跨站请求伪造)

登录受信任的网站A,并在本地生成Cookie,在不登出A的情况下,携带cookie去访问危险网站B/

解决:通过验证码的方式解决

3.SQL注入攻击

就是通过吧SQL命令插入到Web表单递交或输入域名,最终达到欺骗服务器执行恶意的SQL命令。

解决:表单输入时通过正则表达式将一些特殊字符进行转换

html和XML
区别

html被称为超文本标记语言,是一种描述性语言,是构成网页文档的主要语言,它是由很多的标签组成

xml 即可扩展标记语言,是Internet环境中跨平台的、依赖于内容的技术,是当前处理结构化文档信息的有力工具,满足了Web内容发布与交换的需要,适合作为各种存储与共享的通用平台。

共同点

 都可以通过DOM 来访问。都可以通过CSS来改变外观。

 html和xml 都是标记语言,都是基于文本编辑和修改的。   

xml不是要来取代html的,是对html的补充,用来与html协同工作的语言,基于上面这些优势,xml将来成为所有的数据处理和数据传输的常用工具非常可观。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/凡人多烦事01/article/detail/339797
推荐阅读
相关标签
  

闽ICP备14008679号