JS-进阶
1,声明提升
现象:在js的代码中,对于代码片段中的var/let/const/class/function等会提升到代码片段的最前面,然后再执行调整过顺序的代码。
原理: JS引擎的设计: 智能化。即JS会把不符合规范的代码 自动修复后再执行。
除了声明提升以外,js中的隐式类型转化规则也是一种智能化修复。
2,window对象
window对象是一个顶级对象
-
常见方法:
- isNaN() - parseInt/parseFloat() - alert() - comfirm() - prompt() - let timer = setInterval(方法,时间间隔) - clearInterval(timer) - setTimeout(方法,时间间隔)
直接触发的函数,会自动到顶级对象中查找使用,因此在实际使用中可以省略window的书写
全局污染
用var和function在全局作用域中生成的变量默认存储在顶级对象window中,我们称这种情况为全局污染;
全局污染: 顶级对象理论上是存放系统提供的属性, 但是如果把自定义的属性存储在顶级对象里, 就被认为是污染
解决:利用函数作用域或者局部作用域将变量范围限制。
3,作用域
作用域:代码起作用的领域,限定生效的范围
js有四种作用域:
-
全局:脚本中直接书写
-
局部:函数运行时提供
-
块级:ES6提供的
-
模块:Node.js的模块化语法提供的
拓展规定:在外部的js脚本中,一旦需要声明操作,就应该书写一个匿名函数自调用,然后在函数作用域中书写声明操作代码。
好处:
-
不污染全局,不存储在window里,而是在函数的作用域对象里
-
各存各的,不必考虑重名冲突(如果不这样,重名冲突会进行覆盖)
4,作用域链
多层作用域嵌套时会出现作用域链的问题
作用域链:当内存作用域中使用1个变量时,会按照就近原则,先从先从自身查找 -> 找不到就找上级 -> 找不到就继续找上级 -> … -> 直到全局作用域的顶级对象window中 -> 找不到 则是not defined 报错
demo
var x = 10
function a() {
var x = 20
function b() {
var x = 30
function c() {
// var x = 40
console.log(x)
}
c()
}
b()
}
a()
//当依次从里向外注释var声明时打印值会依次变为 40、30、20、10
5,闭包
闭包:closure
代表的是一种状态,本质是函数运行时,产生的作用域对象,但是当前这个对象被保存到其他函数的scopes属性里,这时候就称呼为闭包
为什么要存?因为我们需要用到其中的值,如果存储到scopes当中,就会在函数运行结束后自动释放,导致程序运行失败。
闭包机制:
我用了别人的东西, 我怕别人跑路, 所以把他存到自身内部
闭包的缺点:
因为阻止了内存释放,导致内存一直被占用
6,基于闭包机制的私有变量
JS本身设计了闭包机制,用来保存变量 不允许其释放. 便于函数运行时使用.
很多代码的写法 都会利用闭包机制才能实现
私有变量:通常在封装功能时才会用到
demo
//这里_count就是一个私有变量,
var talk = (function () {
// 命名规范: 如果私有的属性应该加 _ 开头
var _count = 0
return function () {
_count++
console.log('talk次数:', _count)
}
})()
talk()
talk()
talk()
7,arguments
arguments: 函数中提供的一个固有的变量, 存储传入的所有实参
我们在写函数时,并不是每次都能确定函数的形参与实参的数量的,因此在不确定参数的数量或者类型时,需要使用arguments帮我们保存一下传入的参数
demo
function min() {
// 先假设第一个最小, 然后挨个比较 是否有更小的
var m = arguments[0]
for (var i = 0; i < arguments.length; i++) {
var value = arguments[i]
// 语法糖: 通过简化语法来节省代码,简化格式
// 糖: if单分支语句, {}中只有一行代码, 可以省略{}
/*if(value<m){
m=value
}*/
if (value < m) m = value
}
return m
}
console.log(
min(11, 2, 3),
min(453, 12, 324, 34, 32, 31),
);
8,函数重载
函数重载: 这是来自 C Java 等语言的一种概念, 代表可以声明多个同名的函数, 其形参个数不同, 会认为是不同的函数;
JS不存在这种处理机制, 但是函数重载可以有效减少代码. JS中可以通过if判断的方式 实现相同的重载效果
但我们可以通过arguments来实现这种函数重载
demo
//不仅可以使用参数数量判断,参数类型也可以作为判断的依据
function fn1() {
// 利用if判断实参的个数,执行的不同的操作
if (arguments.length == 2) {
操作
}
if (arguments.length == 3) {
操作
}
}
function fn2() {
// 重载的另一种形式: 判断实参的类型 做不同的事情
if (typeof arguments[1] == 'number') {
操作
}
if (typeof arguments[1] == 'string') {
操作
}
}
本人练习代码已经全部上传到gitee仓库,点击可以查看