循环语句
- do while - 先执行,后判断,一般在while()内使用++i - 不管条件是否满足,都会执行一次
- for
- for(循环需要变量的初始值;循环的条件(当满足条件时执行语句块);变量不断向条件外变化(每次循环完成后执行的语句内容))
- 循环需要的变量的初始值仅执行一次,并且不一定需要使用var,需要var的变量 在内循环中,变量定义要到外边,防止重复定义
- 循环需要的变量可以多个定义,使用逗号隔开
- 循环的条件是一个表达式,隐式转换是布尔值,为真时进入语句块,根据循环次数,判断多少次(判断多少次,执行多少次)
- 关于for的死循环
- 可以完成深度遍历
- 例如:
var obj={ value:1, link:{ value:2, link:{ value:3, link:{ value:4, link:{ value:5, link:{ value:6, link:{} } } } } } for(;obj.link;obj=obj.link){ document.write(obj.value); document.write(" ") }
- 注意:
- 当进行从大到小循环时,条件注意 使用 = 问题
- 在双重循环时,不要在内层中判断外层变量或者改变外层变量
- 如果使用break,不写跳出label,它仅跳出当前层循环
- 循环是同步的
- 循环总次数不能超过10亿次,并且循环不能嵌套太多,一般不超过2层
对象
- 对象的创建
- 构造函数创建法
var obj = new Object() - 字面量创建法
var obj={}; var obj=Object.creat({})
- 构造函数创建法
- 键值对
- key:value
- 点语法拒绝使用非字符类型属性
- 在对象中,key 除了字符类型以外,只能支持symbol,都会隐式转换为字符,数值会自动转化为字符,并且数值作为key的获取,必须使用[]语法
- 将对象作为属性,所有对象都会转换为字符,并且都是[object Object]
- 引入存储
- 对象存储在堆中,保存的不是对象本身,而是指向该对象的指针
- 栈(stack):会自动分配内存空间,会自动释放,存放基本类型(String,Number,Boolean,Null,Undefined),简单的数据段,占据固定大小空间
- 堆(heap):动态分配内存,大小不定也不会自动释放,存放引用类型(function,array,object)对象保存在堆中,保存的不是对象本身,而是指向该对象的指针
- JSON
- JSON将对象转成字符串
- 一般转换:
String(obj) -> [ object ] JSON.stringify(obj)将对象转换为JSON格式的字符串
- 一般转换:
- JSON格式字符串转换为对象
JSON.parse(str)- JSON格式
- key必须使用引号引起来
- 字符串必须使用引号
- 最后一个成员不许加逗号
- JSON格式
- 打印对象时不要直接打印,转换成JSON后转换,否则会出现显示错误
- JSON将对象转成字符串
- 对象引用问题
- 若obj1=obj,这两个对象的值都是引用地址,当改变对象内容时,两个对象的值都会改变
- 判断对象是否相等,仅判断地址,而不是判断对象内容
- 可以简单使用JSON.stringify(obj1)===JSON.stringify(obj2)判断是否相等 ,但这种方法有漏洞(后面会修订)
- 垃圾回收机制
- 在堆中的对象可能被若干个变量引用其地址,如果这个对象在后面的内容中不在使用,我们需要将堆中的这个对象清除,否则不会被浏览器自动清除,这样就会造成垃圾的产生,当不断产生这种垃圾时,我们就把这种情况叫做内存泄漏
- 如何阻止内存泄漏
- 先创建每个对象的管理池,针对每个对象所引用它的变量做统一存储管理,如果需要清理该对象时,将引用它的所有变量设置为null。当内存上线达到峰值时,系统会通过垃圾回收车,将这些堆中无引用的对象全部清除回收,这就是垃圾回收机制
- 对象的遍历
- for (变量 in 对象)
- 主要用于遍历对象的可枚举属性,包括自有属性、继承自原型的属性
- 可以简单复制对象
var obj={ a:1,b:2,c:3} var obj1={} for(var pro in obj){ obj1[pro]=obj[pro] } - 后面在介绍
- for (变量 in 对象)
函数
- 函数的创建
- 普通函数创建
function fn1(参数名1,参数名2){函数的语句块}- 这种普通函数的创建,在script标签中被执行时,就放入在堆中,并且在栈中以函数名作为变量引用堆中这个函数地址
- 函数在创建时,就创建了这个函数名的变量,因为它是全局的,所以就会被污染覆盖,覆盖前仍然可以执行当前,覆盖后,函数不能够执行了
- 如果函数中没有使用关键字return,函数会返回一个undefined
- 函数是对象,具备局部引用关系,也可以添加属性,
- console.dir(fn) 将这种对象以对象形式展现
- 匿名函数
- var fn2=function(){ }
- 匿名函数创建,创建好的匿名函数赋值给fn2这个变量,
- 变量什么时候定义,这个函数才会在栈中产生,才可以被调用
- (function( ){ } ) ( )
- 自调用,自执行函数
- 只能执行一次
- var fn2=function(){ }
- 函数的参数
- 在函数后面括号里面填写的变量就是函数的参数
- 如果没有参数,它处理是不能变化的
- 参数目的是使 函数能在不同情况下解决不同 的问题
- 在设计函数时,尽量不要让函数内部与外部有关联,尽量让函数内部是一个独立的个体
- 可以解决抽象问题
- ES5版本中 js中参数不能设置初始值,不填写参数就是undefined
- 定义时的参数叫做形参
- 填入的参数叫做实参,实参是按照形参顺序一一赋值给形参
- 如果实参数目小于形参数量,后面的形参值就是undefined,无法设置初始值,初始就是undefined
- 如果实参数目大于形参时,使用arguments
- 在js中,因为js是一种弱类型语言,因此不能对参数约束其类型,这就会造成,因为使用函数者输入的参数不符合需求而造成代码出错
- arguments的使用
- 只能出现在函数语句块中
- 用于当前函数的参数不固定数量
- arguments.callee 当前函数
- arguments.callee.name 当前函数名字
- arguments.callee.caller 调用当前函数的外部函数
- 普通函数创建
变量的作用域
- 局部变量
- 变量只能在局部中使用
- 被定义在函数内部的变量,使用范围仅在函数内部,并且当前函数执行完成以后,这个变量会被销毁。下一次这个函数在执行时,会重新定义这个变量,并且变量不能被保存在函数执行完成后还能使用
- 优先局部变量,若想在函数内部使用全局变量,可以使用window.变量 。 但ES6中被完全禁止使用
- 如果当前函数内没有定义与全局变量相同的局部变量名时,直接调用全局变量
- 在函数中只要见到使用var定义的变量,这个变量一定是局部变量,而且这个变量被优先
- 如果在函数内部使用var定义变量,遵照局部变量优先原则,不赋值会是undefined
- 当在函数中设置了参数,就相当于这个参数就是被定义好的局部变量
- 一个函数下的局部变量,若函数下有一个内函数执行,当前函数下的局部变量若不是作为内函数的参数,则不会被内函数所调用
- 只要函数有var 这个变量就会是局部变量,不管是在条件里或者循环里
- 全局变量
- 在任何地方都可以使用的变量
函数return返回的作用
- 函数在执行时,将返回函数中的return
- 如果return后面没有内容或者没有return,返回一个undefined
- 可以返回函数的局部变量
- 可以返回参数
- 改变非引用值(除了object,function,array外)时,不会改变外部的值,需要return返回
- 改变引用值,改变一个数据,会把指向相同地址的数据都改变
- 跳出,切断,不继续执行,仅跳出当前函数
函数的回调
- 将一个函数以参数的形式传入到另一个函数中,并且在那个函数中执行,这就是回调
- 一般用于处理事情需要等待时,设置回调
- 超时函数:
- id = setTimeout(超时执行的函数,超时时间,执行函数的参数)
- clearTimeout(id) 清除时间间隔
- 时间间隔函数
- id = setInterval(执行函数,时间间隔)
- clearInterval(id)
- 间隔时间执行一次
- 超时函数:
- 当不需要关心具体后续需要处理的事情时,设置回调
- 把异步等待变成同步间隔
函数的递归
- 函数内部执行当前自身函数,这就是递归
- 根据内存大小设置递归上限次数,如果递归次数太多,就会造成堆栈上限溢出