定义提升(1)
2016-02-25 14:27
465 查看
在《JavaScript权威指南》第六版的4.3节和5.3节中分别讲了函数的两种定义方式:
两者的区别在于函数声明的方式会有一个“定义提升”(hoisting),即将函数声明提升到顶部,这样之后的代码也都可以访问到它。函数表达式的方式则不存在定义提升。通过下面两个例子展示两者的区别:
例子1中虽然是先调用foo,然后才声明的foo函数,但是由于定义提升,foo的声明被提高到顶部,因此foo调用成功。例子1的代码等价于:
例子2中,foo是函数表达式,不存在定义提升,所以先调用后定义的方式是行不通的。和函数声明同样有定义提升的效果的还有var关键字定义的变量,请看下面例子:
因此之前的例子2等价于下面的代码:
由于有定义提升,在同一作用域下所以要特别注意函数同名覆盖的问题。由于多次用var声明一个变量是无所谓的(《JavaScript权威指南》第六版的5.3.1节),这里只需要讨论函数之间同名覆盖、函数与变量同名覆盖两个问题。请看下面的例子:
可以看到函数声明和变量声明的提升,会以函数声明为主。因为在函数执行上下文中,变量声明不会干扰已经存在的同名变量,形参和函数声明。说到执行上下文(EC)又是一个比较大的话题,我把它放到下一篇,这里就略过。
最后再看一个比较综合的例子:
答案:Foo.getName();//2
getName();//4
Foo().getName();//1
getName();//1
解释可以参考最后参考文章中给出的第二个链接,这里就不再赘述了。
参考文章:
1、JavaScript函数声明和函数表达式的区别:函数声明的提升
2、一道常被人轻视的JS前端面试题
函数声明方式: function foo(){} 函数表达式方式:var foo= function(){}
两者的区别在于函数声明的方式会有一个“定义提升”(hoisting),即将函数声明提升到顶部,这样之后的代码也都可以访问到它。函数表达式的方式则不存在定义提升。通过下面两个例子展示两者的区别:
例子1: foo();//调用成功: function foo(){ console.log('ok');}
例子2: foo();//调用失败,"uncaught TypeError: Property 'foo' of object [object Object] is not a function" var foo = function(){ console.log('ok'); }
例子1中虽然是先调用foo,然后才声明的foo函数,但是由于定义提升,foo的声明被提高到顶部,因此foo调用成功。例子1的代码等价于:
function foo(){ console.log('ok'); } foo();//调用成功
例子2中,foo是函数表达式,不存在定义提升,所以先调用后定义的方式是行不通的。和函数声明同样有定义提升的效果的还有var关键字定义的变量,请看下面例子:
例子3: console.log(i);//undefined var i = 1; console.log(i);//1var i =1;可以看成变量定义和初始化两部分,var i; i =1;其中变量定义提升,放在了最开始的部分,而初始化还是留在原地,所以第一次输出的是undefined,第二次输出的是1;
因此之前的例子2等价于下面的代码:
var foo; foo();//调用失败 foo = function(){ console.log('ok'); }这也就说明了为什么报错的内容是“foo不是一个函数”。
由于有定义提升,在同一作用域下所以要特别注意函数同名覆盖的问题。由于多次用var声明一个变量是无所谓的(《JavaScript权威指南》第六版的5.3.1节),这里只需要讨论函数之间同名覆盖、函数与变量同名覆盖两个问题。请看下面的例子:
例子4: function fun1(){alert('A');} fun1(); //结果为 B function fun1(){ alert('B');}可以看到函数声明的提升,会按照出现的顺序进行覆盖。
例子5: (function(a){ console.log(a);//输出函数a的内容 function a(){}; var a=10; }(100))
可以看到函数声明和变量声明的提升,会以函数声明为主。因为在函数执行上下文中,变量声明不会干扰已经存在的同名变量,形参和函数声明。说到执行上下文(EC)又是一个比较大的话题,我把它放到下一篇,这里就略过。
最后再看一个比较综合的例子:
例子6: function Foo() { getName = function () { alert (1); }; return this; } Foo.getName = function () { alert (2);}; var getName = function () { alert (4);}; function getName() { alert (5);} 问: Foo.getName(); getName(); Foo().getName(); getName();
答案:Foo.getName();//2
getName();//4
Foo().getName();//1
getName();//1
解释可以参考最后参考文章中给出的第二个链接,这里就不再赘述了。
参考文章:
1、JavaScript函数声明和函数表达式的区别:函数声明的提升
2、一道常被人轻视的JS前端面试题
相关文章推荐
- JQuery1——基础($对象,选择器,对象转换)
- Android学习笔记(二九):嵌入浏览器
- Android java 与 javascript互访(相互调用)的方法例子
- JavaScript演示排序算法
- javascript实现10进制转为N进制数
- 2019年开发人员应该学习的8个JavaScript框架
- HTML中的script标签研究
- 对一个分号引发的错误研究
- 异步流程控制:7 行代码学会 co 模块
- ES6 走马观花(ECMAScript2015 新特性)
- JavaScript拆分字符串时产生空字符的原因
- Canvas 在高清屏下绘制图片变模糊的解决方法
- Redux系列02:一个炒鸡简单的react+redux例子
- JavaScript 各种遍历方式详解
- call/apply/bind 的理解与实例分享
- 如何创建对象以及jQuery中创建对象的方式
- 数组方法汇总