js高级技巧大总结

-----------------------------------JS高级技巧总结------------------------------------

一.js代码的预编译

在js引擎执行js代码时会首先进行一个预解析,预解析中会有声明的提升,这是一个重要的问题。

会提升var变量名和function的函数,在提升时有一些注意事项,var只提升函数名,function提升的是函数名和函数中存储的值。

1)var提升,不加var的变量是不会被提升的

2)函数提升时有一个例外,在新版的浏览器中如果函数在条件if中就只提升函数名不提升函数值

3)当拿到一段js代码时应该首先想到的是预解析,就是声明的提升

4)当有变量名和函数名都需要提升时,一般情况下不会注意到先提升哪一个

5)当函数名和变量名相同时应考虑先提升函数的声明,再提升变量的声明,后来者可能会覆盖前者的名字,可以看成不用提升

二.js的执行过程

js的执行过程:当js引擎开始执行js代码的时候就产生了一个全局的执行上下文。

在全局的执行上下文中 :1)声明的提升,2)代码的执行

注意代码的执行时从上往下(因为现在的任务都是同步的,从上往下),遇到已经提升过的直接忽略,例如如果是变量名已经提升,就直接赋值,如果是函数直接忽略,因为它提升时是带着值一起提升的。

3)当代码执行过程中调用了一个函数。此时就产生了一个局部的执行上下文,1)形参的赋值,形参的赋值直接可以看做是在该函数内部声明的一个局部变量。2)声明的提升,这里注意提升var变量名,或者函数名和值,是提升在函数内部的最上面,3)代码的执行,从上到下依次执行。

三.var let const和函数声明的注意点

var与不加var的区别:

在全局作用域下:加var与不加var都能看做是window对象的一个属性

在全局作用域下:加var会被提升,不加var不会被提升

在局部作用域下:不加var不会看作是window对象的属性

在局部作用域下:不加var只能是全局变量,不能是局部变量

加var的变量不能被删除,不加var的变量可以被删除

let声明变量的注意:

使用let声明的变量,不能被提升

不能作用于windows对象的属性

不能重新赋值,会报错

let{}会形成一个块级的作用域,块级的作用域能访问外面,外面不能访问块级作用域的数据。

const的注意:

使用const声明的变量,不能重新赋值,相当于声明的是一个常量了。

使用const不能直接 const加变量名,所以在声明的时候就要立刻赋值

ps:我们在做项目的时候,优先选择使用const,如果需要变量是动态的,再其次选择使用let,最后再是var。

四.作用域与作用域链

作用域:

js中的作用域分为局部作用域和全局作用域,局部作用域:当声明了一个函数就产生了一个局部的作用域,在局部作用域以外的作用域是全局的作用域,作用域是静态的哦。它与局部执行上下文和全局执行上下文是不同的,上下文是执行时才有的。

作用域链:

js中的作用域是分为局部作用域和全局作用域,当声明了一个函数就产生了一个局部的作用域。

局部作用域是有上级作用域的,上级作用域看的是函数的声明。

当调用一个函数就产生了一个局部的执行上下文,局部上下文与局部的执行上下文之间是没有关系的。

一个局部上下文会做三件事,形参的赋值,声明的提升,代码的执行。当在一个局部的执行上下文中访问一个变量x,首先在自己的作用域里去找,如果找不到就去上一级去找,不只查找一级,如果找不到就一直查找到全局的执行上下文。

这一过程称为作用域链,也叫作用域的查找机制。

五.arguments 伪数组

arguments是一个伪数组,也可以称为是一个伪类,在函数当中,它可以接收实参的数据,之所以称为伪数组,因为它具有数组得特性,可以通过arguments.length来获取数组的长度。

在该数组中,你可以理解为,它和形参一一对应,当形参改变了,它也跟着改变,反之也是如此。

假如形参有两个,它对应的是arguments的前两项。

如果要传进去的实参数量太多,可以用arguments来接收哦,示情况而定。

六.IIEF

IIEF是立即执行函数表达式,指的是不需要手动去执行,在声明的时候它自己就会调用。之所以引入这一问题是保护函数的内部不受污染。立即执行函数表达式有三种方式。

有三种形式:

第一种形式:

;(function(){})()

第二种方式:

;(function(){}())

第三种方式:

+function(){}();

-function(){}();

!function(){}();

~function(){}();

七.堆和栈内存的分配与释放,闭包

堆内存的分配与释放:

当一个数据是引用数据类型,这个时候就会在内存中开辟一个堆空间来存放这个数据的值,这个对象需要一个变量来引用,如果没有变量来引用这个堆空间,那么浏览器就会在合适的时机去释放掉它。

全局栈内存的分配与释放:

当开始执行js代码就产生了一个全局栈内存。

当js代码执行完毕,关掉了选项卡就释放掉了这个全局的栈空间。

局部栈空间的分配与释放:

当代码执行中,调用了一个函数就产生了一个局部栈。局部栈具有保护作用。

释放:当函数执行完毕后,浏览器就会在合适的时机释放掉这个栈空间。

当函数内部调用自己,如果没有出口就会不停的开辟局部栈空间,最后爆栈,也叫死递归

闭包:当函数调用结束还有别的变量在引用这这块地址,这块栈空间就不会被释放,它里面的数据也会永久保存,这就产生了一个闭包,闭包的优点保护函数中的数据,延长变量的生命周期。缺点:泄露内存。

八.js中的常见错误

(1)let不能重复声明

(2)let和{}会产生一个块级的作用域

(3)let声明的变量名,不能被提升

(4)let声明的变量不属于window对象的属性

九.代码执行过程中的小细节

使用var和不使用var和let一起一些问题,使用let声明从还没执行到它就在内存中有了,但是不提升。所以有些问题还是要注意。

几种错误自己慢慢品:语法错误,引用错误,范围错误,类型错误。

ReferenceError引用错误有两种:第一种:Uncaught ReferenceError: a is not defined

console.log(a)

a=110; //内存中没有,输出一个不存在变量

ReferenceError引用第二种错误:Uncaught ReferenceError: Cannot access 'a' before initialization

console.log(a);

let a=110;//内存中已经有a这个变量了,但是let的声明不会被提升,输出的时候会提示的内存中已定义但是不能引用

SyntaxError语法错误示范一:Uncaught SyntaxError: Unexpected token ')'

if(a>=3)){

 console.log(a)

} //普通语法错误

SyntaxError语法错误示范二:Uncaught SyntaxError: Identifier 'a' has already been declared

let a=110;

var a=123;

console.log(a) //let声明的变量不能重复声明

TypeError类型错误示范一:Uncaught TypeError: a is not a function

 var a=110;

a();

TypeError类型错误示范二:Uncaught TypeError: a is not a function

var arr=[1,2,3,4]

arr()

RangeError范围错误示范一:Uncaught RangeError: Invalid array length

 var arr=new Array(1000000000000000000000000000)

 console.log(arr)//数组长度范围不能太大,超出了数组长度的范围

RangeError范围错误示范二:Uncaught RangeError: Invalid array length

var arr=new Array(-2);

console.log(arr)//数组长度范围不包括负,再说了长度怎么可以是负值呢,超出了数组长度的范围

十.严格模式

(1)整个文件最开头加use strict

(2)函数内部最开头

(3)在es6中默认就处于严格模式

为什么要设置严格模式?

(1)消除js语法中,一些不合理,不严谨的地方,减少一些怪异的行为

(2)消除js代码的一些不安全之处,保证js代码运行安全

(3)严格模式可以比非严格模式下运行得更快

严格模式语法注意有很多:

(1)不允许遗漏声明,不带var

(2)不允许八进制:会报语法错误

(3)不允许把函数写在if中

(4)形参名不允许重复(声明同名的形参)

(5)不允许给对象声明相同的属性

(6)arguments和形参没有以一对应关系

(6)function中的this不再指向window

十一逻辑运算符在js代码中的执行细节

       逻辑与:如果第一个的值为真返回第一个操作数,如果第一个数为假,返回第二个操作数(都是转换之前的数)

逻辑与总结:如果第一个数为假则返回第一个操作数,如果第一个数为真,则返回第二个操作数(都是转换之前的)

0 || false    //false
false || 0 //0
1 || false//1
1 || true //1
"" || fals//false
1 || false//1
"" || true//true
true || ""true
true || 4 //true

"" && 123//""
123 && 0//0
123 && NaN//NaN
-0 && NaN//-0

十二.递归

程序调用自己的编程技巧叫做递归。

把大型的问题层层简化,得到规模小的问题,然后在解决小的问题,再层层解决大的问题

递归函数:在一个函数内部,他自己又调用了自己,需要一个出口

function f(){

          f();//记得需要出口

}

记得解决这几个小例子

 利用递归思想,求100的累加
利用递归思想,求斐波那契数列中的第20项
利用递归思想,求数组中元素的和
利用递归思想,求1,3,5,7,9,... 的第N项的值。索引从0开始。
利用递归思想,求1,3,5,7,9,... 前N项的和
利用递归思想,求0,2,4,6,8,... 的第N项的值
利用递归思想,求0,2,4,6,8,... 前N项的和

猜你喜欢

转载自blog.csdn.net/zwy1231/article/details/103432294
今日推荐