JavaScript学习(4)——prototype原型和作用域

        好记性不如烂笔头,在写作的过程中自己消化吸收,所以写下这个JavaScript学习系列文章。文章中的文字都是自己一一敲字敲下来的,都是自己理解的内容,各位酌情观看。

        上一讲说的作用域,这里还有两个知识点:作用域链声明提升

        先看个很有意思的代码

a = 2;
var a;
console.log( a );

        很多开发者会认为这个会输出undefined(我也是),但它会输出2.为什么呢?这就是变量提升。在上一章节我们在看的《你不知道的JavaScript》书中有说:JavaScript是一门编译型语言,在代码运行之前会先有个编译过程。编译的时候对声明(这里的声明包括变量声明以及函数声明)进行提升。如正常赋值一个变量是 var a=2;在编译器中处理就变成了var a;a=2;在此例子中,就会调整原有的代码顺序,先声明,然后其他代码顺序依次执行


var a;
a = 2;
console.log( a );

这样执行代码结果一眼便知。

除了变量声明,函数声明也是如此。

foo();
function foo() {
console.log( a ); // undefined
var a = 2;
}

        第一行代码执行函数foo(),但foo的声明在第二行。依然是在编译环节对函数foo提升,实际上他会被理解成这种形式

function foo() {
var a;
console.log( a ); // undefined
a = 2;
}
foo();

而表达式赋值则不会

foo(); // 不是 ReferenceError, 而是 TypeError!
var foo = function bar() {
// ...
};

        这里对foo进行变量提升,在执行第一句话的时候,foo是undefined,调用foo()便报错TypeError的错误。

        如果一个名称又有函数声明,又有函数表达式怎么处理?函数优先

foo(); // 3
function foo() {
console.log( 1 );
}
var foo = function() {
console.log( 2 );
};
function foo() {  //这里的函数声明覆盖之前的函数声明,并进行了提升、优先
console.log( 3 );
}
foo();// 2

最终会被处理成

function foo() { 
console.log( 3 );
}
foo(); // 3
foo = function() {
console.log( 2 );
};
foo();// 2

        除了这些细枝末节,作用域链更为重要!当前作用域范围查找某个变量a,a不在当前作用域,js引擎会找到他的上级作用域,并在他上级作用域中查找a变量,找到a则返回a值;否则继续往上级查找,直到全局作用域。全局作用域找不到,报错。

        这里再次重复两个“公式”:

1.函数作用域的含义是指,属于这个函数的全部变量都可以在整个函数的范围内使用及复 用(事实上在嵌套的作用域中也可以使用)。

2.函数的作用域在函数定义的时候就确定了。

此处应该有图,借用。

总结

        我们习惯将 var a = 2; 看作一个声明,而实际上 JavaScript 引擎并不这么认为。它将 var a 和 a = 2 当作两个单独的声明,第一个是编译阶段的任务,而第二个则是执行阶段的任务。 这意味着无论作用域中的声明出现在什么地方,都将在代码本身被执行前首先进行处理。可以将这个过程形象地想象成所有的声明(变量和函数)都会被“移动”到各自作用域的最顶端,这个过程被称为提升。

有了作用域的基础,再讲讲this,就能理解上下文了。所以下篇讲this(no,插播了个闭包)。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值