11/29/2016 8:33:26 AM
面向对象总复习
面向对象的基本概念
三大特征
的方式
自定义构造函数
原型的基本概念以及使用方式
原型链
继承的实现方式
Function
eval
Function的原型链
完整的原型链
Object.prototype的成员
arguments
使用new Function创建出来的函数,函数名.name 为 anonymous 使用var func = function(){} 创建出来的函数,函数名为:func function Person(){}
函数名的扩展
- var func = function(){};
- var func = function Test(){};
- 在test里面可以使用
基础复习 面型对象 高级讲义 ————————————-
递归
- 在函数是内部直接或者间接的调用自己
- 如果没有结束条件,那么递归就是一个死递归
- 递归的两个要素
- 自己调用自己
- 要有结束条件
- 化归思想
- 将问题由难化易,有繁化简的过程,是转化和归结
11/29/2016 10:33:44 AM
递归练习
- 将问题由难化易,有繁化简的过程,是转化和归结
11/29/2016 10:33:44 AM
- 阶乘 求n的阶乘 ## ##
- 函数里面的变量进行返回,外面可以接收
- 打印的空数组是什么????
- 递归应用
- 实现getElementbyId
- 自己实现
- 还是获取所有的元素
- 面试题 11/29/2016 11:39:23 AM
- 自己实现
11/29/2016 2:27:18 PM
作用域以及词法作用域
- 指的就是
- 变量其作用的范围
- js中有且只有函数可以创建作用域
- 词法
- 一旦代码写好,就可以从代码结构分析出来,变量的作用
- 动态作用域(js中没有)
- 今天作用域和动态
- 如果是词法作用域,那么直接按照语法分析,test1访问的是num应该是全局的
- 如果是动态语法作用域,那么久按照自己的运行环境进行分析,就是自己函数里面调用的num
- 块级作用域
- 代码块
- {}
- (js中没有块级作用域)
- 代码块
- 小题目
变量提示
-
js执行分两个阶段
- 预解析
-
- 将函数声明,以及变量的声明提示到其所在作用域的最顶上
- 注意:
- 函数声明会被提示
- 函数表达式不会被提示
- new Function这种形式创建函数 不能被提示
-
- 执行
变量提升中的特殊情况处理
- 当函数同名的时候,都提示,但是后面的会把前面的覆盖掉
- 函数和变量同名
- 只会提示函数声明,忽略变量
- 是先预解析变量,再函数,—>打印函数
- 只会提示函数声明,忽略变量
- 预解析是分作用域的
- 预解析是分段的——–注意: 是预解析分段
- js中的变量和函数提升是分段的(script标签)
代码分段
- js中的变量和函数提升是分段的(script标签)
- script标签说明
条件是函数声明
- 条件是函数声明
- 在新的版本的浏览器啊中,都不支持
- 声明的提升
- 在条件里面加个函数
作用域链
- 概念
- 函数可以创建作用域,函数中又可以声明函数,这样就形成了作用域套作用….
绘制作用域链图
变量的搜索原则
- 当遇到一个变量的使用的时候,先在当前的作用域中去找这个变量,如果找到了就使用
- 如果没有找到,就去外层的作用与众进行查找,如果找到了,就直接使用
- 如果没有找到,就继续往上查找,直到找到0级
- 再找不到就报错
面试
- 声明变量var,如果有同名的全局,就相当于修改
- 如果没,则相当于新增了这个全局变量
- 不推荐使用
- in 关键字
- 用来判断是否可以通过对象来访问某个属性
- 声明全局变量,就相当于给window添加属性
面试题
- 先做变量提示
递归
- 概念
- 在函数内部直接或者间接的调用自己,就是递归
- 划归思想
- 练习题
- 前n项和
- n!
- m的n
- 斐波那契
- 使用递归获取所有的后代元素
- 理解后敲好多遍
作用域
- 理解后敲好多遍
- 变量起作用的范围
- js中能且只能创建作用域的东西是函数
- 词法作用域
- 代码写好的时候根据代码的结构就能确定变量的作用域,—词法
- 对应的是动态作用域,js中没有动态作用域
- 块级作用域
- js中没有
- if for switch 代码块中的作用域
- 作用域链
- 函数可以用来创建作用域,函数中还可以创建函数,所以
- 绘制
- 画一条直线来表示0级作用域链
- 在全局作用域中去参照所有的变量和函数的声明,将其以小方块的形式画在0,作用域上
- 在从0级作用域中的函数涌出新的作用域链,再去查找变量和函数
- 以此往复,就嫩恶搞滑出整个作用域链
- 变量的搜索原则
- 现在使用变量的作用域中进行查找,如果找到了就直接使用
- 如果没有找到,就去上一级作用域链中进行查找,….
- ….
- 变量的提升
- 预解析阶段
- 在预解析阶段,会将所有的变量声明以及函数声明,
- 情况
- 变量和函数同名
- 只函数
- 函数和函数同名
- 都提升,但是会有覆盖
- 变量提示是分段(script)
- 变量和函数同名
- 执行阶段
- 预解析阶段
- 条件是函数声明
- 在条件语句中声明的函数,就是
- 能否被提… 是浏览器版本的问题…
11/29/2016 6:44:44 PM
11/29/2016 8:52:05 PM
函数名扩展
- 函数表达式
-
代码
var func = function(){ console.log('表达式方式的函数') }; func();//表达式方式的函数,可以直接调用
-
- 注意:
- 在使用函数表达式创建函数的时候,
- 后面表达式是可以有函数名的,但是这个函数名不能直接使用。
- 这个函数名,只能在函数内部使用
-
代码
var func2 = function test(){ //只能在这里面进行调用,是死循环,这个函数 //02-函数名的扩展.html:18 Uncaught RangeError: Maximum call stack size exceeded(…) //test(); console.log('我是函数表达式2'); }; //test();//在外面不可以调用通过函数表达式的函数 func2();//只能通过自己赋值的名称去调用 我是函数表达式2
递归
- 在函数内部直接或者间接的调用自己
- 如果没有结束条件,那么递归就是一个死递归
- 递归的两个要素
- 自己调用自己
- 要有结束条件
- 划归思想
- 将问题由难化易,由繁化简的过程,称为化归思想, 是转化和归结的简称
- 案例
-
代码
* 前n项和 * * 5 : 5+前四项和 5+getSum(4) = 5+10 * 4: 4 + 前三项和 4+getSum(3) = 4+6 * 3: 3 + 前两项的和3+getSum(2) = 3+3 * 2: 2 +前一项的和 2+getSum(1) = 2+1 * 1: 1 1 function getSum(n){ if(n==1){ return 1; } return n+getSum(n-1); }; console.log(getSum(5));
-
-
求n的阶乘 n!
代码 阶乘 求n的阶乘 n! /* *阶乘 求n的阶乘 n! * 5 : 5 * product(4) * 4 : 4 * product(3) * 3 : 3 * product(2) * 2 : 2 * product(1) * 1 : 1 * */ function product(n){ if(n==1){ return 1; } return n*product(n-1); }; console.log(product(3));//6
-
求m的n次方
/* * 求m的n次方 m , n * m : m * m * m *m * m m的5次方 * m : m * m * m *m m的4次方 * m : m * m * m m的3次方 * m : m * m m的2次方 * m : m m的1次方 * m : m * 前四项的n-1次方 * 公式: m * pow(m,n-1) * */ function pow(m,n){ if(n==1){ return m; } return m * pow(m,n-1); }; console.log(pow(2,3));//8
- 斐波那契1 1 2 3 5 8
-
代码
/* * 1 1 2 3 5 8 * 斐波那契 * 1 * 1 * fb(n-1)+fb(n-2) * */ function fb(n){ if(n==1||n==2){ return 1; } return fb(n-1)+fb(n-2); } console.log(fb(4));//3
-
递归应用
变量提升
- js执行分两个阶段
- 预解析
- 将函数声明,以及变量的声明提升到其所在的作用域的最顶上
- 执行
- 预解析
- 注意:
- 函数声明会被提升
- 函数表达式不会被提升
- new Function这种形式创建的函数 不能被提升
-
代码
/2.函数表达式不会被提升//*1.函数声明会被提升*/ fn1();//fn1调用 function fn1(){ console.log('fn1调用'); }
fn2();//08-变量提升.html:19 Uncaught TypeError: fn2 is not a function(…) var fn2 = function(){ console.log('fn2调用'); } /*3.new Function这种形式创建的函数 不能被提升*/ fn3();//Uncaught TypeError: fn3 is not a function var fn3 = new Function('console.log("fn3调用")');
变量提示中的特殊情况处理
- 当函数同名的时候,会都提升,但是后面的会把前面的给覆盖掉!!!
- 当函数和变量同名的时候, 只会提升函数声明,忽略变量
- 预解析是分作用域的
-
代码
//当函数同名的时候,会都提升,但是后面的会把前面的给覆盖掉!!! fn();//fn-----02 function fn(){ console.log('fn----01'); } function fn(){ console.log('fn-----02'); } //当函数和变量同名的时候, 只会提升函数声明,忽略变量 /*test();//test()--- function test(){ console.log('test()---'); } test = 123;*/ // 预解析是分作用域的 test();//test() var test = 2; function test(){ var num = 10; function num(){ } console.log('test()'); } console.log(test);//2 /*分析预解析*/ //注意: 变量和函数同名字的时候,函数的声明优先,所以变量的var test不在了 function test(){ var num = 10; function num(){ } console.log('test()'); } test();//'test()' test = 2; console.log(test);//2
预解析是分段的
- js中的变量和函数提升是分段(script标签)的
- 就是在自己的script中访问不到别的script中的值
- 自己的总结注意:
- 变量的时候,预解析分段,
- 执行不分段,是从上到下执行的,上面有的话,可以进行打印
- 函数也是一样的,预解析分段,执行不分段
- 没问题,执行是从上到下执行的
- 变量的时候,预解析分段,
-
代码
<script> // fn1();//第一个fn function fn1(){ console.log('第一个fn1'); } //Uncaught ReferenceError: fn2 is not defined(…) // fn2(); // console.log(num1); </script> <script> fn1();//第一个fn1 var num1 = 10; fn2();//第二个fn2 function fn2(){ console.log('第二个fn2'); } </script>
条件式函数声明
- 在新的版本的浏览器中,都不支持
- 数声明的提升
- 自己的理解
- 条件满足的情况下
- 函数的调用在函数的声明之前是会报错的,因为条件函数不支持函数的声明
- 但是变量是支持条件函数中的声明的
-
代码
//test();//Uncaught TypeError: test is not a function(…) /* if(true){ function test(){ console.log("我是在if语句中声明的函数"); } }*/ //我是在if语句中声明的函数 //test();//如果条件为真,在函数声明的下面,可以进行整除的调用 console.log(num);//undefined if(true){ var num = 10; } console.log(num);//10
- 补充的11/30/2016 1:50:52 PM :
- 条件式函数声明
- 只会提升函数名!!!不会提升函数体!!!!
-
代码案例
/*代码的执行 * 条件式函数声明可以进行在外部拿到foo的声明.... * */ console.log(foo);//undefined if("foo" in window){ console.log(foo);//foo(){} //解析成函数表达式的形式,所以 // var foo = function(){}; function foo(){} }
作用域链
作用域链概念
- 概念
- 函数可以创造作用域,函数中又可以声明函数,
- 这样就形成作用域套作用域的链式结构,称作作用域链
-
代码
function test1(){ function test2(){ function test3(){ } } }
绘制作用域链
- 绘制步骤
- 先画一条直线,用来表示0级作用域链
- 然后在全局作用域中,查找变量以及函数的声明,以小方块的形式,将其画在0级作用于链上
- 再从0级作用域链中的函数中引出新的直线,用来表示1级作用域链
- 在去对应的函数中查找变量以及函数的声明,以小方块的形式,将其画在1级作用于链上
- 再沿着当前作用域一直往里找,找到一个函数画一条线,以此重复,直到找不到函数为止
- 例子
变量的搜索原则
- 当遇到一个变量的使用的时候,先在当前的作用域中去找这个变量,如果找到了,就直接使用
- 如果没有找到,就去外层的作用域中进行查找,如果找到了,就直接使用
-
如果没有找到,就继续往上查找,直到查找到0级作用域链
-
代码案例
function f1(){ var num =10; } function f2() { f1(); console.log(num); } f2();//Uncaught ReferenceError: num is not defined(…)
面试题
- 注意:
- (不推荐使用)声明变量如果不使用var关键字,就相当于如果有同名的全局变量,则是修改其值
- 如果没有同名的全局变量,则相当于新增了这么一个全局变量
- in 关键字 用来判断是否可以通过对象来访问某个属性
- 声明全局变量,就相当于给window对象新增了一个属性
- 变量声明提升
-
代码
// 01 /* var num = 123; function f1() { //去访问的全局变量 console.log( num ); } function f2() { //去改的全局变量 num = 456; f1(); } f2();//456*/ //02 /* var arr = []; for ( var i = 0; i < 10; i++ ) { arr.push( i ); } for ( var i = 0; i < 10; i++ ) { console.log( arr[ i ] ); }*/ //0-9输出,for循环中的i是同一个,下面使用的时候,将i改了 /* function foo() { var num = 123; console.log(num); // } foo();//123 console.log(num); //num is not defined(…)*/ /* var scope = "global"; function foo() { //找自己作用域下面的 console.log(scope); //undefiend var scope = "local"; console.log(scope); //local } foo(); //找自己的全局变量 console.log(scope);//global*/ //03 /* if("a" in window){ var a = 10; } alert(a);//10*/ //变量提升 /* var a; if("a" in window){ a = 10; } alert(a);//10*/ //4 var foo = 1; function bar() { //是判断自己变量!undefiend 是true if(!foo) { var foo = 10; } alert(foo); //10 } bar(); /* 解析过程 var foo; function bar() { if(!foo) { var foo = 10; } alert(foo); //10 } foo = 1; bar();*/ // console.log(!undefined);//true 11/29/2016 11:55:19 PM
复杂的面试题目
<script>
/*
*分析步骤
* 1. 先将函数和变量的预解析进行变化
* 2. 划出函数和原型链和全局变量的范围和对应的值
* 3. 注意:
* 1.Foo().getName();
* 2. new的时候,代码的执行顺序
* */
/* function Foo() {
getName = function(){ alert(1); };
return this;
}
Foo.getName = function() { alert(2); };
Foo.prototype.getName = function(){ alert(3); };
var getName = function() { alert(4); };
function getName(){ alert(5); }*/
/*变量和声明提升后的代码*/
function Foo() {
getName = function(){ alert(1); };
return this;
}
function getName(){ alert(5); }
Foo.getName = function() { alert(2); };
Foo.prototype.getName = function(){ alert(3); };
getName = function() { alert(4); };
/*最后一个是4,将之前的5给覆盖掉了*/
getName(); // 4
//Foo()当成普通的函数去调用,getName去修改全局的变成1
Foo().getName(); // 1 先执行Foo()当成正常的函数进行调用,返回的是window对象,再进行调用全局的getNmae函数
getName(); // 1 访问的是上面函数改过的1
new Foo.getName(); // 2, 先调用后面的,是静态函数的方法
new Foo().getName(); // 3 先创建一个对象,访问到是原型里面的3
new new Foo().getName(); // 3 先执行第二个new创建一个对象,去调用原型链中的方法ok
</script>
11/30/2016 12:32:14 AM