JavaScript_概念篇

1、作用域和作用域链

作用域:函数内变量的可用性的代码范围

作用域链:当你要访问一个变量时,首先会在当前作用域下查找,如果当前作用域下没有查找到,则向上一级作用域进行查找,直到找到全局作用域,这个查找过程形成的链条叫做作用域链。

多个上下级关系的作用域形成的链,它的方向是从下向上的(从内到外)查找变量时就是沿着作用域链来查找的。

作用:起到隔离变量,防止冲突

2、原型和原型链

原型:是function对象的一个属性,它定义了构造函数制造出的对象的公共祖先。通过该构造函数产生的对象,可以继承该原型的属性和方法。原型也是对象。

该function对象可以通过“.prototype”访问原型。构造函数实例化对象通过传递参数,让不同的实例化对象拥有不同的值。构造函数内部定义的属性是可以直接看到的,而“.prototype”的属性和值需要访问才能看到。利用这一特性,可以将公共部分提取出来,用“.prototype”的方式来定义,需要不同值的属性交由构造函数来定义。

Person. prototype = {
    height : 1400,
    lang : 4900
}
function Person (width){
    this.width = width
}
var person1 = new Persion(200)
var person2 = new Persion(300)
​
Person.prototype === person1.__proto__

原型链:构造函数通过“.prototype”可以修改所属原型,构造函数产生的对象可以通过“.__ proto__”来访问他的原型,逐层往上找

3、同步和异步

同步是阻塞模式,异步是非阻塞模式。

同步就是指一个进程在执行某个请求的时候,若该请求需要一段时间才能返回信息,那么这个进程将会一直等待下去,直到收到返回信息才继续执行下去;

异步是指进程不需要一直等下去,而是继续执行下面的操作,不管其他进程的状态。当有消息返回时系统会通知进程进行处理,这样可以提高执行的效率。

4、闭包

当内部函数被保存到外部时,将会生成闭包。闭包会导致原有作用域链不释放,造成内存泄露。

作用:可以读取函数内部的变量,让这些变量的值始终保持在内存中。

function text(){
  var a = 1
  return function log(){
    console.log(a)
  }
}
text()//如此,便通过return的方式把log函数就被保存下来了

5、== 和 ===

 "==" 只判断等号两边的值是否相等,而不判断类型是否相同。值相同则返回 true

 "===" 既要判断值是否相等,也要判断类型是否相同,即全等才能返回 true

"==" 相等运算符

相等运算符用来比较相同类型的数据时,与严格相等运算符完全一样。相等运算符隐藏的类型转换,会带来一些违反直觉的结果。推荐使用严格相等运算符

1、原始类型的值(string,number等基础类型) ​ 原始类型的数据会转换成数值类型再进行比较

2、对象与原始类型值比较 ​ 对象(这里指广义的对象,包括数组和函数)与原始类型的值比较时,对象转化成原始类型的值,再进行比较

3、undefined 和 null ​ undefined 和 null 与其他类型的值比较时,结果都为 false,它们互相比较时结果为 true

"===" 严格相等运算符

1、不同类型的值 ​ 如果两个值的类型不同,直接返回false

2、同一类的原始类型值 ​ 同一类型的原始类型的值(数值、字符串、布尔值)比较时,值相同就返回true,值不同就返回false

3、复合类型值 ​ 两个复合类型(对象、数组、函数)的数据比较时,不是比较它们的值是否相等,而是比较它们是否指向同一个地址

4、undefined 和 null ​ undefined和null与自身严格相等

6、虚拟Dom的实现

当用原生 js 或 jquery 等库去操作 DOM时,浏览器会从构建 DOM 树开始讲整个流程执行一遍,所以频繁操作 DOM 会引起不需要的计算,导致页面卡顿,影响用户体验。

浏览器内核拿到html文件后,大致分为一下5个步骤:

1、解析html元素,构建dom 树

2、解析CSS,生成页面css规则树(Style Rules)

3、将dom树 和 css规则树关联起来,生成render树

4、布局(layout/ reflow),浏览器会为Render树上的每个节点确定在屏幕上的尺寸、位置

5、绘制Render树,绘制页面像素信息到屏幕上,这个过程叫paint

虚拟DOM:是由普通的js对象来描述DOM对象(浏览器执行js很快)

当数据改变后,diff算法重新比较新老DOM树(Vue优化diff算法,同层级比较,标签名比较,key值比较),计算出最小的变更,在操作DOM,更新视图。

7、this 关键字

this:指向一个对象,该对象被称为函数执行时的上下文对象

1、在函数中,this 会指向当前调用函数的元素 ​ 2、如果没有元素调用函数,this会指向window

8、同步、异步、宏、微

JS 是单线程,所有任务需要排队,前一个任务结束,才会执行后一个任务。如果前一个任务耗时很长,后一个任务就不得不一直等着。

问题: 如果 JS 执行的时间过长,这样就会造成页面的渲染不连贯,导致页面渲染加载阻塞的感觉。

为了解决这个问题,利用多核 CPU 的计算能力,HTML5 提出 Web Worker 标准,允许 JavaScript 脚本创建多个线程,但是子线程完全受主线程控制。于是,JS 中出现了同步任务和异步任务。

同步任务:在主线程上排队执行的任务,只有前一个任务执行完毕,才能执行后一个任务。

异步任务:不进入主线程、而进入“任务队列”的任务,当主线程中的任务运行完了,才会从“任务队列”取出异步任务放入主线程执行。异步任务又分为宏任务和微任务

宏任务:定时器 setTimeout、计时器setInterval、事件绑定、ajax、回调函数、异步的I/O操作等

微任务

  • promise:promise 的 then 方法中执行的代码就属于微任务。具体来说,当 promise 的状态变为 resolved(即调用了 resolve 函数),且有 then 方法注册时,then 方法中的函数就会被放入微任务队列中,等待 javascript 引擎执行。

  • async/await:async/await 实际上是基于 promise 实现的语法糖。使用 async 关键字定义的异步函数内部可以使用 await 关键字来等待 promise 对象返回结果,并且 async 函数的返回值也是一个 promise 对象。因此,async/await 语法中涉及到的代码都属于微任务。

  • mutationobserver:mutationobserver api 可以监听 dom 节点的变化,并在发生变化时执行回调函数。回调函数中的代码也属于微任务。

同步任务——>异步任务(微任务——>宏任务)

console.log("window同步任务1");                       //1
​
function asyn(mac) {
  console.log("function同步任务2");                   //2、7
  
  if(mac){  console.log(mac)  }                      //8
  
  return new Promise((resolve, reject) => {
    console.log("function-Promise中的同步任务");      //3、9
    resolve("function-Promise中回调的异步微任务")      
  })
}
​
setTimeout(() => {
  console.log("setTimeout异步任务中的宏任务 宏+同");    //6
  
  setTimeout(() => {
    console.log("定时器中的定时器 宏+宏+同");           //11
  }, 0)
  
  asyn("定时器传递任务").then(res => {
    console.log('setTimeout-asyn定时器中的:', res);    //10
  })
  
}, 0)
​
asyn().then(res => {
  console.log(res);                                   //5
})
​
console.log("window同步任务3")                         //4
​
​
•window同步任务1    
•function同步任务2
•function-Promise中的同步任务
•window同步任务3
•function-Promise中回调的异步微任务
​
•setTimeout异步任务中的宏任务 宏+同
•function同步任务2
•定时器传递任务
•function-Promise中的同步任务
•setTimeout-asyn定时器中的: function-Promise中回调的异步微任务
•定时器中的定时器 宏+宏+同

9、异步编程

JS 是被设计用来操作网页 DOM 元素,如果多个JS线程同时操作 DOM 元素必然出乱子,所以 JS 被设计为单线程,但单线程又会导致代码阻塞。

通过异步解决阻塞问题,异步借助消息队列和 EventLoop(事件循环) 来实现

Promise 之前,回调套回调,容易形成回调地狱,代码向右增长,可读性差

fn1(function(){
    setTimeout (function(){
        setTimeout (function(){
            xxx
        },3000)
    },1000)
})

Promise 之后,可以通过 then 方法,链式调用,代码向下增长

function p1(){
    return new Promise(()=>})
}
​
function p2(){
    return new Promise(()=>{})
}
​
function p3() {
    return new Promise(()=>{})
}
​
p1().then(p3).then(p2)    //then表示之后执行的意思

在 Promise 中,当一个错误被抛出时,Promise 链会自动跳过剩余的then()方法,并直接进入到下面的catch()finally()方法。

fetch("https://jsonplaceholder.typicode.com/ posts/1")
.then((response) =>response.json())
.then((json) =>{
    console.log(json);
})
.catch ((error) =>{
    console.error ( error);
})
.finally(()=> { });

async、await ,提供了一种更简洁的方法来处理异步操作

async声明异步函数。异步操作可以在该函数中被调用和执行,随着异步任务被处理,返回一个Promise对象。

async function foo() {
  // 异步操作
}

await 等待一个异步任务完成。在此期间,JS 引擎可以去其他地方做一些任务,当异步操作完成时,在回到这个await表达式的位置,继续执行后面的逻辑。

async function foo() {
    const result = await someAsyncOperation();
    console.log(result);
}
async function f(){
    const promiseA = fetch( "http://.../post/1" );
    const promiseB = fetch ( "http://.../post/2" );
    const [a, b] = await Promise.all([promiseA, promiseB]);
}
async function f(){
    fer (let i of [1,2,31){
        await someAsyncOperation();
    }
    console.log(" done");
}
f();

在上面的代码片段中,someAsyncOperation()函数是一个异步操作,如果没有await关键字修饰,程序将不会阻塞,在这个函数上继续执行。通过采用await关键字并暂停该函数的执行,等待异步函数完成,这样就可以利用回调函数的方式处理异步操作。

10、promise

Promise 是 ES6 引入的异步编程的新解决方案(回调地狱)。语法上 Promise是一个构造函数,用来封装异步操作并可以获取其成功或失败的结果。

Promise 是异步编程的一种解决方案,其实是一个构造函数,自己身上有all、reject、resolve这几个方法,原型上有then、catch等方法。

把异步任务封装在Promise的对象里面,通过 resolve 和 reject 两个参数来改变状态,再通过 then 方法接收回调,一般通过 value 接收成功的回调,season 接收失败的回调。通过 then 方法的链式调用避免回调地狱。

11、箭头函数和function函数

function 函数,this 的指向随着调用环境的变化而变化的,指向其直接调用者,一般来说最通常的是window对象;

箭头函数中的 this 指向是固定不变的,一直指向的是定义函数的环境,并且this 的指向无法通过其他方式改变。

由于箭头函数没有自己的 this,所以当然也就不能用call( )、apply( )、bind( )这些方法去改变 this 的指向。箭头函数不能使用new生成构造函数,因为箭头函数没有 prototype,而 construct 在 prototype 里面。

function 存在变量提升,可以定义在调用语句后;function存在变量提升,可以定义在调用语句后;

12、数组常用方法

1、实现数组的增删改的方法 ​ push: 向数组末尾增加内容 ​ unshift: 向数组开始位置增加内容 ​ pop: 删除数组最后一项 ​ shift: 删除数组中的第一项 ​ splice: 实现数组的删除、替换、增加 ​ replace:字符串替换方法

2、数组的查询、拼接 ​ includes: 检测数组中是否包含某一项 ​ slice: 实现数组的截取 ​ concat: 数组拼接 ​ join: 把数组中的所有元素放入一个字符串

3、数组的排列或者排序 ​ reverse:倒叙 ​ sort: 小到大排序(大于10需要传参)

push做方法的时候是给从数组最后一个数据开始增加新的数据,但是做为返回值的时候输出的是该数据的长度;

pop做方法的时候是删除数组最后一个数据,做为返回值的时候是输出当前删除数据的值;

13、模拟数据的入栈和出栈

栈是一个先入后出的有序列表,可以看成特殊的队列,它限制了数据的插入和删除操作只能在线性表的同一端(栈顶)。

插入:在栈中插入操作称为入栈,最先放入栈中的元素在栈底,最后放入的元素在栈顶。

删除:在栈中删除操作称为出栈,最先删除的元素在栈顶,最后删除的元素在栈底。

14、获取 dom 元素

getElement选择器

1、通过ID获取 ——document.getElementById('id')

2、通过name属性 ——document.getElementsByName('name')

3、通过标签名 ——document.getElementsByTagName('div') ​ 参数是是获取元素的标签名属性,不区分大小写 ​ 返回值是一个类数组,没有找到返回空数组

4、通过类名 ——document.getElementsByClassName('content') ​ 返回值是一个类数组,没有找到返回空数组

querySelector选择器

1、获取第一个元素 ——document.querySelector('.animated')

可获取标签【div】,类【.content】,ID【#content】

2、获取一组元素 ——document.querySelectorAll('.animated') 返回类数组 ​

15、Math常用方法

向上取整:Math.ceil(1.4) ==> 2

向下取整:Math.floor(1.4) ==> 1

随机数: Math.random( ) ==> [0,1) 

16、...

        ...

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值