函数的作用域:
- 概念: 就是变量可以起效果的范围
- 目的: 为了提高程序的可靠性更重要的是减少命名的冲突
全局作用域 && 局部作用域:
全局作用域:(直接在script内 或者 在一个单独的JS文件内书写的代码)
在此作用域创建的变量,我们叫做全局变量,在当前script 标签内的哪里都能使用
<script>
var num =100
console.log(num);
在JS中,全局作用域只有一个 提前给我们准备好的 对象(一种数据格式);这个对象叫做: window
我们创建的全局变量,会被自动添加到 window 对象中
var abc = "我是一个全局变量 ABC "
console.log(window);
</script>
局部作用域:(在JS中,只有函数能够创建局部作用域所以也可以叫做: 函数作用域)
在此作用域创建的变量,只能在当前作用域使用,超出这个作用域(也就是在函数外部) 是不能使用的
<script>
function fn(){
var sum1 = "我是函数在 fn 内创建的变量,我是局部变量,所以只能在当前函数内使用"
console.log(sum1);
}
fn()
console.log(sum1);
</script>
作用域链:
- 概念: 内部函数访问外部函数的变量,采取的是链式查找的方式来决定取哪个值,这种结构我们称之为作用域链;
访问规则:
- 在访问一个变量的时候,如果当前作用域内没有,会去自己的父级作用域内查找,如果找到了就直接使用,如果没有找到就继续向上层查找;直到查找到 最顶层的全局作用域,如果找到了就直接使用,如果没有找到,报错会提示变量不存在(未定义)
访问规则案例1:
<script>
function fn1(){
var num = 100
function fn2(){
console.log(num);
}
fn2()
}
fn1()
</script>
访问规则案例2:
<script>
function fn1(){
function fn2(){
console.log(num);
function fn3(){
var num = 666
}
fn2()
}
fn2()
}
fn1()
</script>
访问规则案例3:
<script>
var num = 999
function fn1(){
function fn2(){
console.log(num);
}
fn2()
}
fn1()
</script>
赋值规则:
- 在给变量赋值的时候,首先会去当前作用域查找变量,如果有直接赋值,并停止查找;如果没有,会去自己的父级查找,在父级找到直接重新赋值然后停止查找.如果没有继续向自己的父级查找,直到找到全局作用域;在全局作用域内,找到了就直接重新赋值修改它的值,如果没有找到,那么会在全局作用域创建一个变量,并赋值;
赋值规则案例1:
<script>
function fn1(){
function fn2(){
num = 100
}
fn2()
}
fn1()
console.log(num);
</script>
赋值规则案例2:
<script>
function fn1(){
var num = 999
function fn2(){
num = 100
}
fn2()
}
fn1()
console.log(num);
</script>
递归函数:
- 概念: 本质上还是一个函数.当一个函数在函数的内部,调用了自身,那么就算是一个所谓的 递归函数(只不过有点小缺陷)
简单的递归函数:
<script>
function fn(n){
fn()
}
</script>
写一个简单的递归:
案例分析递归函数:
<script>
function fn(n){
if(n===1){
return 1
}
return n * fn(n - 1)
}
var sum = fn(4)
console.log(sum);
</script>
步骤:
简单了解对象:
- 概念: 是JS中的一种数据格式,对象在JS中的数据类型数据为: 引用数据类型(也叫复杂数据类型)
- 储存对象的语法: 语法1: var obj = {键值对 key:value}
语法的使用:
在下边这个对象中:
a 为key,100 为对应的 value
另一种叫法: a 为键 ,100 为对应的值
另一种叫法: a 为属性名,100为对应的属性值
<script>
var obj = {
a:100,
b:200,
c:300,
q:666
}
console.log(obj)
</script>
创建对象:(分为两种方式)
1.字面量方式创建对象:
语法:var obj = {键值对}
<script>
var obj = {
a:100,
b:200,
c:"300",
d:"abc",
e:undefined,
w:null,
r:function(){
console.log("我是obj 对象 内 r 这个属性的属性值,我是一个函数")
}
}
console.log(obj)
</script>
2.内置构造函数创建:
语法1: var obj1 = new Object()
语法2: var obj1 = new Object({a :1,b:2})
注意: new Object 的 O 是大写的,不是小写;
<script>
var obj1 = new Object({
a:100,
b:200,
c:"300",
d:"abc",
e:undefined,
w:null,
})
console.log(obj1)
</script>
对象内对于 键(key) 的要求:
1.推荐使用符合变量命名规则与规范的名字 ->(一般公司推荐使用这一种,后两种不常见)
2.对象的 key 也可以使用 纯数字 来当做键名(属性名/key)
3.可以使用任何特殊符号(但是需要使用引号包裹)
4. 对象内部有多个 键值对,那么需要用 逗号 间隔开
对象数据类型的操作(增删改查)两种语法:
点语法:
点语法增删改查的使用:
<script>
var obj = {
a: 11,
b:"qwe",
c:true
}
console.log("原始对象:",obj);
obj.q = "QF001"
obj.f = 111
console.log("最新的对象:",obj);
delete obj.a
console.log("删除属性后的 obj:",obj);
obj.c = false
console.log("修改属性后的对象:",obj);
console.log(obj.a);
console.log(obj.b);
</script>
中括号语法(数组语法):
中括号的增删改查的使用:
<script>
var obj = {
a: 11,
b:"qwe",
c:true
}
console.log("原始对象:",obj);
console.log(obj["a"]);
console.log(obj["c"]);
obj["r"] = 12345
obj["w"] = 789
console.log("新增后的obj:",obj);
obj["b"] = "QF001"
obj["c"] = false
console.log("修改后的obj:",obj);
delete obj["a"]
console.log("删除属性后的obj:",obj);
</script>
两者的差异:
- 相同: 点语法与中括号语法,作用相同;
- 不同点: 特殊情况下我们需要使用中括号语法:
1.对象的属性名,有纯数字或者特殊符号,这个时候,就只能使用中括号语法
<script>
var obj = {
100:"我的属性名是 纯数字 100",
'@':'我的属性名是 特殊符号 @',
'!':'我的属性名是 特殊符号 !'
}
console.log(obj[100]);
console.log(obj["100"]);
console.log(obj["!"]);
console.log(obj["@"]);
</script>
2.如果涉及变量相关的时候,也需要使用中括号
<script>
var obj1 = {
a:1,
b:2,
name:"QF001"
}
var myName = "name"
console.log(obj1.myName);
console.log(obj1[myName]);
</script>
for in 循环遍历对象:
for...in: 一个循环语句
对象: 一种数据格式
遍历:一般我们会说 " 遍历对象" /'遍历数组'
"遍历对象" 想办法拿到对象内部所有的 属性名与属性值
语法: for(var i in 要遍历的对象){循环要执行的代码}
案例:
<script>
var obj = {
a:1,
q:"qwe",
t:true,
u:undefined
}
for(var i in obj){
console.log(obj);
console.log(obj.i);
console.log(obj[i]);
}
</script>