学习内容:
- 作用域
- 递归函数
- 复杂数据类型:对象
- 基本数据类型 复杂数据类型 赋值在内存的区别?
作用域:
提示:
域 就是 区域 就是范围 变量 可以生效使用的范围
分类:
- 全局作用域 (公家的 )
浏览器打开一个html 页面 这个页面就是全局作用域
window
在整个html页面,变量都可以拿来用
- 局部作用域(函数作用域\私有作用域)
只有函数有局部作用域
function 函数名(){}
if else if for while do while 都有大括号,但是他们不叫局部作用域
- 作用域的级别
定义在哪个作用域的函数,就是哪个作用域的子集作用域 function fn1(){ // 大括号内部 就是fn1的私有作用域 // 父级 全局 window // 子级 fnbmn2 function fn2(){ // 大括号内部是fn2的私有作用域 // 父级 fn1 // 子级 fn3 function fn3(){ // 大括号内部是fn3的私有作用域 // 父级 fn2 } }
变量的机制:
-
定义变量 变量的定义机制
变量在哪个作用域下,就是哪个作用域的私有变量
function test(){ var num = 100; // num就是test 的私有变量 }
变量定义了,只能在自己的作用域或者后代作用域内使用
alert(num1); // 报错 num1 is not defined; function test(){ var num1 = 200; alert(num1); // 正常使用 function new_test(){ alert(num1);// 正常使用 } }
-
访问变量
- 首先 在自己的作用域内 如果有这个变量 直接使用 停止查找
- 如果自己的作用域内没有 那么就会到父级作用域查找 如果有 直接使用 停止查找
- 如果父级作用域没有 再到父级的父级作用域查找
- 以此类推 直到全局作用域 window 都没有 那么就报错 ** is not defined
-
赋值给变量
- 当你需要给一个变量赋值
- 现在自己的作用域下查找是否有这个变量 如果有直接赋值停止查找
- 如果没有 主动到父级作用域下查找 如果有直接赋值 停止i查找
- 如果还没有 再往上一级查找
- 以此类推 直到 全局作用域 window 如果window 有 给到window 下的变量赋值 window 没有
- 就把这个变量定义为全局变量 再进行赋值
注意事项
声明新的变量 要加关键词var 不加var 变量就变成了一个全局变量 作用于全局 坏处: 全局变量 只要html页面不关闭 永远在内存待着 局部变量 如果函数执行完成,变量的空间也会跟着释放 开发的时候尽可能的减少全局变量
递归函数:
一种函数的调用方式 一个高阶的函数调用方式
函数可以调用另外一个函数
同理 函数自己也可以调用自己
什么是递归函数:
- 函数自己调用自己
- 正确设置了结束条件
递归函数的技巧:
- 写个函数
- 设置结束条件
- 未达到结束条件的 一定要 写return
对象:
对象 也是javascript 一个数据类型 复杂数据类型 Object
对象数据类型 Object:
也是个盒子 这个盒子中放着很多数据
复杂的数据类型
无序的数据集合 (多个数据放在一起就是集合)
每一次的数据顺序都不一样 => 无序
每一次的顺序都一样 => 有序
是一个键值对 的集合
对象的创建方式:
- 字面量 的方式创建
一个对象 就是一个字面量
var 名字 = {}; // 创建一个空对象 var 名字 = { 键值对, 键值对,}
- 内置构造函数的方式 简单说 就是 new
var 名字 = new Object();
对象 对于 键 key 的要求:
- 建议使用标识符的命名规则和规范
- 可以使用纯数字 当键名
- 使用纯数字作为键名的时候 这个键值对会排在最前面
- 可以使用特殊符号作为键名
- 使用特殊符号,再书写的时候 必须加单引号 包裹
- 键的名字 要避开关键字 和保留字
对象的操作:
增 create 在对象内 增加一个键值对
删 delete 在对象内 删除一个键值对
改 update 修改 对象内键值对的数据
查 read select 访问 对象中的 键值对
- 点语法 .
- 增 对象名.键名 = 值; // 对象中没有这个键, 给这个新的键赋值 = 增加一个键值对
- 删 delete 对象名.键名;
- 改 对象名.键名 = 新值; // 这个键一定是已经存在的键 然后重新赋值
- 查 对象名.键名
- 如果有这个键 那么就输出这个键对应的 值
- 如果没有这个键 那么就是undefined
- 数组语法 []
- 增 对象名['键名'] = 值; // 这个键不存在 给一个新的键赋值
- 删 delete 对象名['键名']
- 改 对象名['键名'] = 值;
- 查 对象名['键名']
if 中 写条件 比如判断 键是否存在 用数组语法
区别:
1. 当键的名字 满足标识符的命名规则和规范 它俩没有区别
2. 当键的名字是纯数字 或者里边有特殊字符,只是使用数组的语法方式
进行增删改查
3. 里边涉及到变量 把键的名字赋值给 变量 ,然后对象通过变量 拿到 指定的值
只能使用数组的语法方式 中括号内也不要加单引号
对象的遍历:
- 查看是否有指定的键 in
- 把键或者值或者键值对挨个取出来 for in
in 关键字
'字符串' in 对象名 => 一定是一个布尔类型 true 表示 对象 有这个键 false 表示 对象没有这个键 in 只能判断 键是否存在于 对象中 不能判断 某个值是否存在于 对象中
for .. in 循环
for(var 变量 in 对象名){ // 多少个键值对 循环多少次 // 每次循环 变量中存的是对象的 键 // 每次循环 对象名[变量名] 键对应的值 }
基本数据类型和 引用数据类型:
赋值的区别:
1 . 基本数据类型 赋值 会在栈内存开辟一个新的空间 两个空间独立
两个变量就没有任何关系了
2. 引用数据类型赋值 因为 引用数据的名字在栈内存 赋值也会在栈内存开辟一个新的空间 两个栈内存的空间同时指向一个堆内存空间 所以 一个变量进行修改 另外一个 也跟着改变
不同数据类型的存储 :
基本数据类型存在栈内存中
引用数据类型 的数据本体在堆内存 名字在栈内存 栈内存的空间存着堆内存空间的地址