-
递归
(1)找规律(把复杂问题转化成相对简单的问题);
(2)找出口(特定规律找已知值);
(3)循环改变i的值,是否是可以循环的预期所期待的,也就是是否是对相关内容造成影响。
(4)递归的空间复杂度跟时间复杂度是最高的。
示例:求斐波那契数列Var result=0; Function mul(num){ If(num==1||num==2){ Return 1; } Return mul(num-1)+mul(num-2); }
-
函数
JavaScript 使用关键字 function 定义函数。 函数可以通过声明定义,也可以是一个表达式。
比较常用的定义的三种方式:
a. function functionName(parameters)
{执行的代码}:直接定义
b. var x = function (a, b) {return a * b};:
显式函数表达式,a,b是形参,a,b是未生声明的,直接调用x.a为null。
如果a和b有具体的值则是实参。
c. var y = function () {执行代码};:隐式函数表达式
d. 获取形参个数,可以用.length来获取。 -
形参、实参
示例:
Function fun1(param1,param2){ // param1,param2为形参
Console.log(param1,param2);
}
Fun1(param1,param2); // param1,param2为实参
(1) js天生不定参
调用函数当实参比形参多时不会报错,会把所传的参数都存在Arguments属性里;
(2) 简单类型和引用类型
简单类型:var a=1;
var b=a;
b=2;
console.log(a);1//简单类型的变量使b等于a,无论如何改变b的值,a都不会改变
引用类型:var a={x:111};
b=a;
b={y:222};
console.log(a); {x: 111}//引用类型的变量使b等于a,给b重新赋新值,a不会改变
如果b.y=222;
console.log(a); {x: 111, y: 222}//引用类型的变量使b等于a,直接改变b的值(新加属性y),a发生改变
(3) 实参与形参多的时候可以用arguments。如果实参比形参短,后面不够的全为undefined。形参比实参短,则正常显示。
(4) java中不定参用:public static void(int … args) -
变量作用域:全局变量、局部变量
-
JS三部曲(语法分析、预编译、解释执行)
(1) 通篇扫描,语法分析,如果存在逻辑错误或者语法错误,那么直接报错,程序停止执行
(2) 方法执行的前一刻,进行预编译
预编译四步:
1) 创建AO对象
ao{
}
2) 将函数内所有的形参和变量声明储存到ao对象中,value为undefined
ao{
a:undefined,
b:undefined,
}
3) 将形参和实参进行统一
ao{
a:1,
b:undefined,
}
4) 将所有的函数声明的函数名作为ao对象中的key,函数整体内容作为value,存储到ao对象中
ao{
a: function(){},
b: function(){},
}
示例:
function test(a,b){
console.log(a);
var a=123;
function a(){}
console.log(b);
var b=234;
console.log(b);
function b(){}
console.log(a);
var b=function(){}
console.log(b);
}
test(1); 结果:ƒ a(){} ƒ b(){} 234 123 ƒ (){} -
(1)所有全局变量都是window的属性
(2)未经声明就赋值的变量都是全局变量 -
(1)函数声明整体提升
(2)变量声明提升 -
作用域原理解析
上面代码执行情况演示:
作用域链:
当某个函数第一次被调用时,就会创建一个执行环境(execution context)以及相应的作用域链,并把作用域链赋值给一个特殊的内部属性([scope])。然后使用this,arguments(arguments在全局环境中不存在)和其他命名参数的值来初始化函数的活动对象(activation object)。当前执行环境的变量对象始终在作用域链的第0位。
以上面的代码为例,当第一次调用fn1()时的作用域链如下图所示:
(因为fn2()还没有被调用,所以没有fn2的执行环境)
可以看到fn1活动对象里并没有scope变量,于是沿着作用域链(scope chain)向后寻找,结果在全局变量对象里找到了scope,所以就返回全局变量对象里的scope值。
自我理解:局部变量:从ao里找;
全局变量:从ao找不到,往上层找(GOwindow)
9. toFixed(num):方法可把 Number 四舍五入为指定小数位数的数字。num是必需,规定小数的位数,是 0 ~ 20 之间的值,包括 0 和 20,有些实现可以支持更大的数值范围。如果省略了该参数,将用 0 代替。返回 NumberObject 的字符串表示,不采用指数计数法,小数点后有固定的 num 位数字。如果必要,该数字会被舍入,也可以用 0 补足,以便它达到指定的长度。如果 num 大于 le+21,则该方法只调用 NumberObject.toString(),返回采用指数计数法表示的字符串。当 num 太小或太大时抛出异常 RangeError。0 ~ 20 之间的值不会引发该异常。有些实现支持更大范围或更小范围内的值。当调用该方法的对象不是 Number 时抛出 TypeError 异常。
注意number.toFix(num)是Number对象中的一个函数,它不会改变number的值,并且返回值的类型是String类型。
9. 累加一般从0开始,累乘从1开始。
10. null是object类型,+a有隐式类型转换Number(a).
11. 取两个非的作用:如果传的参数是true或者false,为了保证参数是boolean类型
如:alert(typeof(null))—“object”
var a = “123abc”;
alert(!!a)—两个取非—保证结果一定是Boolean值。
a = !a --false;
a = !a –true
target = Boolean(target) 等价于 target = !!target;
12. 栈内存与堆内存
当定义值类型的时候,在栈内存中有一个值,变量名指向它。改变值的时候会重新开辟空间存放新的值,并改变指向。
当定义引用类型的时候:在堆内存中存放内容,在栈内存中开辟一个空间存放对应的地址,然后变量名指向这个地址。
13. 未经声明的变量严格意义上来说只有typeof不会报错;