全文总计7500字,代码和符号约为3000字符,正文约4030字,预计阅读约20分钟
扩展阅读:JS基础函数的参数
旧版本(ES6之前):var function
var:通用的,可以省民变量,储存任意类型的值
var a=1,b=true.....
function:只能晟敏函数,声明一个变量来存储函数
function c(){
}
作用域:具有一个特殊作用的对象类型
在JS里面万物皆为对象
全局作用域 用于存储系统API【接口】
宿主与寄生:寄生虫-寄生在什么物体上,这个物体就是宿主
JS运行在什么环境中,这个环境就叫宿主
比如:JS运行在浏览器上浏览器就是宿主
JS就能使用浏览器的各种功能
console.log(window)
如下图

这是什么数据类型呢?

我们可以看到,他是个对象的类型所以我们可以调用他来是先
比如 alert是浏览器提供的最基础的弹窗组件
例如:
<script>
window.alert("hello world!");
script>

所以:凡是存在window中的–称为全局对象或全局作用域
由于window是专门存储API的对象,所以也成为 作用域
在全局作用域里面,前面的(window.)可以省略
全局污染:是用来存放系统API的如果把我们自己定义的属性放在全局作用域中,就叫全局污染
window:是用来存放系统API的
通过var在script中声明的变量,会存储在window里面,就是全局污染–把自定义的放在系统的API存储的地方就是全局污染
js有两个作用域,分别是全局和局部作用域
全局作用域在浏览器就是window对象
局部作用域:函数运行时所产生的对象
函数:静态+触发态
如下图,如果没调用函数mian()是否能正常打印a,b,c呢?

结果是没有出现

因为函数只是声明的还没有出发出来,换句话说就是,函数没调用,没调用就相当于没有声明函数所以a,b,c没有被声明
所以当我们调用函数之后就有了值


当调用函数之后a,b,c就会被声明
那么abc存储在那里呢?全局?
我们在window(全局声明)里面是没看到的
答案是:函数作用域,这个是在函数运行期间临时生成的,在运行结束的时候会自动销毁
调试面板DOM断点

本地创建的临时作用域

代码如下
<body>
<script>
var a=10,b=20
console.log(a+b);
console.log('全局:',window);
script>
body>
结果产生了全局污染

解决方法:把代码在函数里执行–利用局部作用域结局全局变量污染,变量自然会存储在函数作用域而且执行完毕后,还会释放内存
而全局window声明变量直到页面管不,储存在这里的函数会一直存活下去,直到页面关闭
注意点:和上一行要有一个分号间隔,要不然可能会产生错误,也可以在前面加一个分号,没上一行则可以不用间隔
为什么匿名:没名字的函数,仅仅是为了执行一次而已,提供一个局部作用域
格式
<body>
<script>
(function(){
// 代码写在函数里,所有声明的代码都在函数作用域
})();
script>
body>
所以代码可以这样写
<body>
<script>
;(function(){
var a=10,b=20;
console.log(a+b);
console.log('全局:',window);
})()
script>
body>
结果:这次没有污染全局作用域

为什么不会产生全局污染呢?
如下图

原因:因为生成的变量等是放在函数作用域里面的,使用完之后会销毁掉所以不会对全局产生污染

声明提升:JS的编辑器会先阅读提取代码中的声明操作然后提到顶部在去执行调整过顺序的代码
首先来看两demo,来了解一下声明提升

除了js之外的语言类似的代码都是打印:‘1111,2222’这是JS的特殊设定,
因为JS引擎会把声明代码进行提升然后再去执行如下图



var a=function(){
console.log(1);
}
是由两行代码合并起来的
拆开就是
var a
//声明操作
a=function(){
console.log(1);
}
// 赋值操作
当JS在处理时…

看下案例

函数分为两种状态:静态和动态(调用)
函数为什么能用到外部的声明——作用域链
当出现多层作用域嵌套的时候
会一层一层往上去找——就近原则-优先使用离得比较近的
比如下面这个案例打印的就是小新

优先使用最近的
局部作用域-函数作用域:·临时生成的对象,函数运行结束后会销毁,达到节省内存的目的
看示例猜猜下面的结果看:
<script>
// 函数分为两种状态:静态和动态(调用)
// var uname="小宝"
function show(){
var uname ='小新'
var b=function(){
console.log(uname);
}
// b()
return b
}
var b=show() //show函数调用后的结果
b()
</script>

为什么会有结果呢?
解析:
如果在一个函数作用域内,例如在b函数里面uname在另外一个函数中被使用了,而我们为了确保函数能永远正常运行,JS就会让这个b函数 把用到的uname所用到的作用域保存下来,防止被其释放,导致无法使用,
运行:
console.dir(b)

简单的来说就是能用到的数据,会连作用域一起宝留下来不会被销毁
闭包:用于形容被保存下来的函数作用域

相当于:

再来看一个案例
<script>
(function () {
var a = 10;
var b = 20;
function x() {
var a = 30;
var c = 40;
function y() {
var d = 30;
function z() {
var e = 60;
console.log(a, b, c, d, e);
// ?
}
z();
}
y();
}
x();
})();
script>
函数scopes属性:储存·使用到的··来自其他作用的变量 所在的作用域——防止其他作用域自动销毁
已知e是自己作用于的
所以就为:

由于就近原则所以scopes的数组大致就为:
scopes:[
0:closure y(d:50)
1:closure x(b:30,c:40)
2:closure (a:10)
3:galobal window //全局
]
接下来验证一下

事实证明的是对的
私有:只能自己,不让别人用
<script>
// 只能自己,不让别人用
(function(){
var money=1000
function shan_bigjian(){
money-=100
console.log("做了个大保健还有:",money,"元")
}
shan_bigjian()
shan_bigjian()
// 小新也去做了大保健还是pro max
function xin_bigjian(){
money-=300
console.log("小新用阿山的钱做了个大保健还有:",money,"元")
}
xin_bigjian()
xin_bigjian()
})()
script>

如何不让阿山的钱被小新用 ?
方式:把money放在一个函数作用域里运行不放在公开的位置(不放在自己显眼的位置,自己带着)—使用匿名函数快速制作一个私有的作用域

修改后就为:


现在只能自己用了
但是现在只能在内部用,我想在外部函数使用(相当于只能偷偷用,我想光明正大的用)
实现:


现在数据只能拥有的函数可以用了,其他函数用不了【小新就无法使用阿山的钱了】
解析:

函数重载:可以让函数功能增强变为多功能函数
比如:制作一个双十一折扣价格的函数的
<body>
<script>
// 制作一个双十一折扣价格的函数的
function zhekou(x, y, z) {
// console.log(typeof y);
// arguments保存了函数触发时收到的所有实参
if (arguments.length == 3) {
// 满减
// console.log(arguments);
if (x <= y) {
return x - z;
} else {
return x;
}
} else if (arguments.length == 2) {
// 打折/vip
// console.log(arguments);
if (typeof y == "string") {
if (y == "vip1") {
return x * 0.7;
} else if (y == "vip2") {
return x * 0.55;
}
} else if (typeof y == "number") {
return x * y;
}
}
}
console.log(zhekou(3000, 0.7));
console.log(zhekou(1000, 0.9));
console.log(zhekou(1000, "vip1"));
//0.8折
console.log(zhekou(1000, "vip2"));
//0.55折
console.log(zhekou(2000, 2000, 500));
//满两千-500
console.log(zhekou(2000, 2000, 700));
//满两千-700
script>
body>
结果

实现判断满多少减多少和折扣的判断:因为arguments存了传入的所有数据,所有用arguments.lengch来判断参数
实现折扣和vip优惠:判断第二个数据类型使用typeof,但是对比的参数最好时字符【带引号,不加会报错】
数据返回:return返回的数据,不会直接打印出来,要打印一下
请用3s秒找到下面的错误
<script>
var bnumm = (function () {
var num = 100;
return function b() {
num--;
console.log("b is num", num);
b();
};
})();
bnumm();
script>