0624 NOTE
1.对象
key:value 键值对 一一对应 可以通过键找到值,查找速度非常快
键值与键值之间没有关联 松散结构 向对象中添加和删除新的键值对的速度非常快
对象没有键值对的数量统计,键值对之间也无顺序,遍历是按照键值对的添加顺序遍历
但是打印展示时按照key字母unicode编码顺序展示
key的类型是字符串或者(symbol),不是则会隐式转换为字符串
创建方法:
var obj = {a:1,b:2}; //字面量创建法
var o = new object(); //构造函数创建法
添加属性:
var a = "b";
//变量作为key时,key相同时会覆盖
var obj = {a:1,b:2,"c":1,[a]:3}; // [a] => "b" => b:3
obj.d = 10; //obj添加新属性d,值为10
console.log(a); //b
console.log(obj.a) //1
console.log(obj[a]) //3
var a = "b";
var o={b:{}}; //创建一个对象o,属性为b,值为{}
o.a=10; //增加属性a,值为10
o.b.a=1; //属性b的值新增属性a,值为1
o[a][a]=2; //属性b的值新增属性b,值为2
o[a]=20; //修改b值为20
o["b"]=20; //修改b值为20
o.b=20; //修改b值为20
console.log(o);
var o={a:1,b:2};
var c,b;
o[c]=20; //新增属性undefined,值为20
var o1={a:1};
var o2={b:2};
o[o1]=30; //新增属性[object Object],值为30
console.log(o)
栈与堆:
数据结构是数据存储的形式
栈是向低地址扩展的数据结构,堆是向高地址扩展的数据结构,两者都是内存空间
栈顶的地址和栈的最大容量是系统预先规定好的,空间较小,内存区域连续
堆的大小则受限于计算机系统中有效的虚拟内存,空间较大,但是内存区域不连续
栈与堆类似于内存与硬盘的关系
栈中存储数据类型为Number、string、Boolean;具有快速读取的特性
堆中存储数据包括:对象、数组、链表、树等等
栈中数据:变量:值/地址
堆中数据:引用地址:数据 引用列表(用null清理)
引用类型:栈中存储了变量以及该数据在堆中的引用地址
undefined是在栈中开辟空间但未赋值,null并不存在在变量的概念中
var obj = {a:1};
console.log(obj.a); //1
console.log(obj); //{a:10} 数据存储在堆中,在进入堆中查找数据前,a为1,
//进入堆中查找是代码已经执行完后的数据,因此,a是10
obj.a = 10;
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gR3RH6a3-1624679886696)(C:\Users\86183\AppData\Roaming\Typora\typora-user-images\image-20210624173651279.png)]
var obj = {a:1};
//obj = null;
obj = {a:2}; //没有将obj赋值为null,虽然仍旧可以正常运行,但是有可能造成内存泄漏的问题
//js具有自动的垃圾回收机制 谷歌会清理掉没有引用的对象,其他浏览器不会
浏览器缓存机制:
第一次进入浏览器,存入缓存
第二次进入时,已加载,因此控制台对象直接显示,但是过多时会有省略
JSON.stringify(); //将对象转换为字符串,JSON格式字符串
JSON.parse(); //将JSON格式字符串转换为对象(每个属性会加上双引号)
var o = JSON.parse(JSON.stringify()); //可以实现深复制,但是,只能复制数值、字符串、
//数组、对象、undefined等
2.函数
函数特点:将功能抽象化
函数式编程:功能全部分别放在不同函数中
console.dir() //将函数当作对象打印
函数的创建方式:
function fn(){}; //命名函数创建法
var fn = function(){}; //匿名函数创建法
var fn = new Function(); //构造函数创建法
(function(){})(); //自执行函数
var obj = {a:function(){}}; //对象方法
函数在执行script标签创建时,就会将函数名存储在栈中,并且在堆中存储函数体,栈中变量函数名存储函数体的引用地址
命名函数会在作用域创建开始就进行预解析,匿名函数则是在定义之后才能使用
函数参数就是变量,而且是局部变量
参数的目的是为了让函数内部独立,不影响外部的数据
函数通过传入的参数完成各种需求,没有调用外部全局变量,也不会影响全局变量,这种函数叫纯函数
型参与实参:
形参:函数在传参时,函数中定义的变量
实参:执行函数时,传入形参的值或变量
获取函数的形参数量:函数.length
js中函数参数传入时,无法约束数据类型,可能会导致 传入不同类型数据造成错误,因此在函数开放给他人使用时,参数必须做严格的条件判断处理
ES5中参数是没有默认值,统一默认值都是undefined,但是中间不写参数是不可以的
ES6中参数可以设置默认值
一般认为,必填参数写在前面,有默认值的参数写在中间,选填参数写在后面
//参数过多,不确定传入数量
// ES5 可以不用定义参数
function fn(){
console.log(arguments);//是一个列表,像数组
arguments.length //实参数量
console.log(arguments.callee)//当前函数,用在匿名函数中,严格模式下不可使用
console.log(arguments.callee.caller)//调用当前函数的外部上下文函数
}
fn(1,2,3,4,5,6,7);
// ES6 ...变量
function fn1(...arg){
console.log(arg);//数组,数组里面就是所有实参
}
function fn1(a,...arg){
console.log(a,arg);//数组,数组里面就是所有实参
}
// fn1(1,2,3,4,5,6,7);
3.作用域
在块作用域中全局变量的赋值结果是最后一个同名函数之前的上一次赋值
var a = 3;
{
a = 4;
function a()[
console.log(1);
]
a = 5;
function a(){
console.log(2);
}
a = 6;
console.log(a); //6
}
console.log(a); //5
局部变量是指函数内部创建的变量
局部变量有效的作用范围就是当前函数以及当前函数内部嵌套各种函数和对象中
函数执行开始会将当前函数内所有使用var定义局部变量在函数所在的独立栈空间
开辟这个变量,但是并没有赋值,等到函数执行赋值时才赋值,之前的结果都是undefined
当函数执行完成后,如果当前函数没有返回内部创建函数或者对象存储全局变量时,
则函数体内的所有局部变量将会被销毁
参数相对于函数内变量或者函数先定义先赋值
js中作用域只有全局作用域以及局部作用域(函数作用域),ES6新增了块作用域
{
var a;
funtion a(){
} //语法错误,a重复声明
}
- 在块级作用域中默认声明的变量,只有代码执行到声明语句之后,才可以进行访问,否则会报错。
- 块级作用域中默认声明的变量会被提升到全局作用域。
- 块级作用域函数在编译阶段将函数声明提升到全局作用域,并且会在全局声明一个变量,值为undefined。同时,也会被提升到对应的块级作用域顶层。
- 块级作用域函数只有定义声明函数的那行代码执行过后,才会被映射到全局作用域。
console.log(window.a,a);//undefined undefined
{
console.log(window.a,a);//undefined function a(){}
function a() {};
a = 10;
console.log(window.a,a); //function a(){} 10
};
console.log(window.a,a); //function a(){} function a(){}
在这里,首先,块级作用域函数a的声明会被提升到全局作用域,第一行打印比较符合预期。然后在块级作用域中,由于声明函数a提升到块级作用域顶端,所以打印a = function a(){}
,而window.a
由于并没有执行函数定义的那一行代码,所以仍然为undefined
。当执行到声明函数定义的时候,就会把函数a映射到全局作用域中。当执行a = 10
的时候,JS引擎会进行LHS查找,此时,声明函数已经被同时提升到全局作用域和块级作用域顶端了,由于遮蔽效果
,此时查找a只会找到块级作用域内的a,并不会找到全局作用域的a,这时,a已经被定义,a = 10
只会执行赋值操作,并不会进行提升。
console.log(window.a,a);//undefined undefined
{
console.log(window.a,a);//undefined function a(){}
a = 10;
function a() {};
console.log(window.a,a); //10 10
};
console.log(window.a,a); //10 10
此时,在块级作用域中函数声明已经被提升到顶层,那么此时执行a,就是相当于赋值,将函数声明a赋值为数字a。然后,执行到函数声明语句,此时,虽然这一行代码是函数声明语句,但是a,已经为数字10了,所以,执行function a(){}
之后,a的值10就会被赋值给全局作用域上的a,所以下面打印的window.a,a
都为10
块级作用域函数只有执行函数声明语句的时候,才会重写对应的全局作用域上的同名变量。
块级作用域内的变量声明不会提升到全局作用域的顶层
详细链接:https://zhuanlan.zhihu.com/p/100856823