JavaScript
循环语句
do……while
- do{ 循环语句; }while(循环条件);
- 先执行,再判断条件是否继续循环
- 不管条件是否满足,至少执行一次语句
for
-
for(变量的初始值;循环条件;变量变化){ 循环语句; }
- 1、循环需要变量的初始值仅执行一次,并且不一定需要使用var
- 2、循环的条件是一个表达式,隐式转换为布尔值,为真时进入语句块,根据循环次数判断多少次
- 3、变量向条件外变化(这个理解比较片面)。每次循环完成后执行的语句内容
- 注:var定义写在循环外,防止重复定义
- 关于for 的死循环 for(;;){} 不加任何条件,就形成了死循环
- for的深度遍历 var obj={ value:1, link:{ value:2, link:{ value:3, link:{ } } } } for(;obj.link;obj=obj.link) console.log(obj.value);
for……each
for……of
递归
注意事项
- 当进行从大到小循环时,条件注意使用=的问题
- 在双重循环时,不要在内层中判断外层变量或者改变外层变量
- 如果使用break,不写跳出label,它进跳出当前层循环
- 循环是同步的
- 循环不能此处超过10亿次,循环不能嵌套太多,一般不超过2层
对象
对象的创建
- 1、var obj=new Object(); 构造函数创建法
- 2、var obj={}; 字面量创建法
- 3、var obj=Object.create({});
Key
-
字符型key
- var obj={ key:value; };
-
变量型key
- var a =”keys” var obj={ [a]:16 }
-
key如果不是字符串,就不能使用点语法 点语法拒绝使用非字符类型属性 点语法只能写明确的字符型属性,其他都只能用中括号
-
在对象中key除了字符类型以外只能支持symbol类型(除symbol类型外都会转为字符串)
-
对象的值可以通过变量改动,地址不能改动
对象的引用存储
-
对象存储在堆中
- 对象存储在堆中,会产生地址,栈中变量拿到该地址,然后去堆中查看
- 打印名称只是打印了地址,点击箭头表示去查找地址对应的值,因此写在后面的也会改变
- 刷新页面,显示的是当前的结果不是改变后的内容,点击箭头依然是改变后的内容,并没有显示错误(不要去点击打印看结果)
-
JSON
-
对象转换为JSON格式的字符串
-
JSON.stringify(obj)
- JSON格式字符串‘{“a”:1,”b”:2,”c”:”xietian”,”checked”:true,”o”:{“d”:1}}
- 这时能显示当时的值
-
-
将JSON格式字符串转为对象
- JSON.parse(obj)
- 不符合JSON格式要求的会报错,错误信息如下 Unexpected token b in JSON at position 7 at JSON.parse ()
-
-
对象的引用关系问题
-
两个变量都是同一个引用地址,所以当改变对象的内容时,他们的值都改变
-
判断两个对象是否相等
- 仅判断地址,而不是内容
-
如何解决判断内容是否相等
- 用JSON转换后判断(有漏洞,不够全面,可能出错)
-
对象的属性和方法
-
删除对象
-
不删除会造成 堆栈内存同时溢出,报错如下 Maximum call stack size exceeded 不同时溢出时,没有报错,但会造成卡顿
-
内存泄漏
- 在堆中的对象可能被若干个变量引用其地址,如果这个对象在后面的内容中不再使用,我们需要将堆中的这个对象清除,否则不会被浏览器自动清除,这样就会造成内存垃圾的产生,当不断产生这种垃圾时,我们就把这种情况叫做内存泄漏
-
如何垃圾回收(处理内存泄漏)
- 先创建每个对象的管理池,针对每个对象所引用它的变量做统一存储管理,如果需要清理该对象时,将引用它的所有变量设置为null,当内存上限达到峰值时,系统会通过垃圾回收车将这些无引用的对象全部清楚回收,这就是垃圾回收机制
-
-
遍历对象 for in
-
for(var 变量名 in obj){ console.log(变量名,obj[变量名])};
- 属性间没有任何关系,散列
-
对象的遍历是通过添加属性的先后顺序遍历的
-
对象的复制
- 通过遍历复制、不是深度复制
- 深度复制、对象的深复制=>用JSON
-
-
删除对象属性 delete obj.a
-
对象方法
-
对象属性后跟了函数
- JSON不能将对象中的方法进行转换
-
如果函数中没有使用return 函数返回undefined值
函数
函数是一个对象,存储在堆中
函数的创建
-
普通函数声明
-
function fn1(arg1,arg2)
{ // 函数的语句块 console.log("a"); }
- 普通函数创建,在script被执行时,就放入堆中,并且在栈中以函数下作为变量引用堆中这个函数地址 - 位置在scrip中可任意放置 - 函数在创建时就创建了含这个函数名的变量,因为是它是全局变量所以会被其他污染覆盖,覆盖前让然可以执行当前函数,覆盖后,函数不能被执行 - 函数是对象,因此具备引用关系
-
-
匿名函数声明
- var fn2=function(){ // 函数的语句块 console.log("aaa"); }
fn2();
- 创建好的匿名函数赋值给变量 - 变量什么时候定义,这个函数的变量才能在栈中产生,才可以被调用
-
自执行自调用
-
(function(){
console.log("aa"); })()
- 自动执行,只能调用一次,以后不能再被调用
-
-
Function构造函数
-
var fn=new Function("a","b","console.log(a+b)");
- 构造函数创建,每个参数都必须是字符串
- 除了最后一个参数是函数的语句块以外,前面所有的参数都是该函数的参数
-
函数的参数
-
在函数后面括号中填写的变量叫做参数
-
为什么要填写参数:函数如果没有参数,它处理时是不能变化的
-
目的是解决函数在不同情况下,解决不同问题
-
在设计函数时
- 尽量不要让函数内部与外部有关联
- 尽量让函数内部是一个独立的个体
-
函数是 抽象出解决事情的方法,而不是解决事情
-
JS是一种弱类型语言,因此不能对参数约束其类型,这就会造成没因为使用函数者输入的参数不符合需求而造成代码出错,不能通过白盒测试
-
JS中参数不能设置初始值(ES5版本中),不填写参数就是undefined
-
函数定义时的参数叫做形参,内部执行的时候是实参
- 实参是按照形参顺序一一赋值给形参的
- 如果实参数量小于形参数量,后面形参的值就是undefined
arguments的使用
-
定义函数时没有定义参数,如果实参数量大于形参数量,使用arguments
-
arguments只能出现在函数语句块中
-
用于当前函数的参数不固定数量
-
相关属性
- arguments.callee 当前函数
- arguments.callee.name 当前函数的名字
- arguments.callee.caller 调用当前函数的外部函数
变量的作用域(敲重点)
-
变量分类
- 在任何地方都可以使用的变量叫做全局变量
- 只能在局部中使用的变量叫做局部变量
-
被定义在函数内部的变量,使用范围仅在函数内部,并且当前函数执行完成以后,这个变量会被销毁,下次该函数再执行时,会重新定义这个变量,并且变量不能被保存在函数执行完成后使用
-
局部变量和全局变量名称相同且同时使用,用window调用(ES6被禁止)
-
如果当前函数内没有定义与全局变量相同的变量名,直接调用全局变量
-
优先调用局部变量
- 打印变量早于定义该局部变量之前打印undefined,仍然遵照局部变量优先原则
- 在函数中只要看到使用var 定义的变量,这个变量就一定是局部变量,而且这个变量被优先
- 当在函数中设置了参数,那么就相当于这个参数就是被var定义好的局部变量
- 参数本身就是局部变量,所以重新定义不赋值是不起作用了
-
没有在函数内使用var,意味着当前a是全局的
XMind: ZEN - Trial Version