JavaScript DOM编程艺术学习笔记(一)

153 阅读3分钟

这是我参与更文挑战的第11天,活动详情查看:更文挑战

原创声明

文章曾被多个网站转载,特此声明一下,图灵社区原文和掘金本文,均为本人创作,其余出处为他人转载。 本篇为学习《JavaScript DOM编程艺术》的学习笔记。

前言

在JavaScript引擎正式编译之前,会进行一次预编译,在这个过程中,会将变量声明及函数声明提升至当前作用域的最顶端,其后才进行接下来的处理。

变量提升

未使用块级作用域:

源代码:

console.log(msg);// undefined
var msg = "This is a message";
console.log(msg);// This is a message

function fn () {
  console.log(hello); // undefined
  var hello = 'hello world';
  console.log(hello); // hello world
}
fn();

JavaScript解析器的解析流程:

var msg;// 变量提升,全局作用域范围内,此时只是声明,并没有赋值
console.log(msg);// undefined
 msg = "This is a message";// 此时才赋值
console.log(msg);// 打印出This is a message

function fn () {
	var hello;// 变量提升,函数作用域范围内,此时只是声明,并没有赋值
  console.log(hello); // undefined
  hello = 'hello world';// 此时才赋值
  console.log(hello); // hello world
}
fn();

ES5只有全局作用域和函数作用域,而ES6开始提供了块级作用域。使用ES6语法的let创建的变量和const语法创建的常量,均不存在变量提升。

使用块级作用域:

console.log(msg);//Uncaught ReferenceErrord
let msg = "This is a message";//没有被执行
console.log(msg);//没有被执行

function fn () {
  console.log(hello); //Uncaught ReferenceErrord
  let hello = 'hello world'; //没有被执行
  console.log(hello); //没有被执行
}
fn();

IIFE与块级作用域

一般的JavaScript函数有三种写法。

1.函数关键字,也叫函数声明语句写法

function foo(){}; foo();

2.函数字面量,也叫函数表达式写法

var foo = function(){}; foo();

3.funtion()构造函数

var foo = new function(): foo();

有时需要在定义函数之后,立即调用该函数。这种函数就叫做立即执行函数,全称为立即调用的函数表达式IIFE(Imdiately Invoked Function Expression)。 通过立即调用的函数表达式,能够实现块级作用域的效果。

JavaScript引擎规定,如果function关键字出现在行首,一律解释成函数声明语句,而且声明语句必须要有一个函数名。所以如下的代码demo会报错。

function () {}; //Uncaught SyntaxError: Unexpected token (

正确的写法是给函数声明语句提供一个函数名。

function foo() {}; //undefined

接下来将函数声明语句与JavaScript分组操作符进行组合,看上去这样的组合好像并没有什么意义,并且会抛出一个错误:

function foo() {} (); //Uncaught SyntaxError: Unexpected token )

错误在于JavaScript分组操作符需要指定一个值,不能为空。

正确的组合写法:

function foo() {} (0);//0

function foo() {}; (0); //0 两种写法等价。

这样也仅仅是实现了函数声明语句与不报错的分组操作符的组合。

所以需要将函数声明语句改成函数表达式写法,将function使用分组操作符进行组合。这样就不需要再指定一个函数名。这个表达式将会在加载网页时立即执行,而不需要单独调用函数。执行后,函数内代码块声明的变量将只在局部作用域内有效。无法被外层访问到。

(function () {} () );

或者

(function () {}) ();

在ECMAScript6中,由于块级作用域的出现,实际上使得获得广泛应用的立即执行函数表达式(IIFE)不再必要了。

// IIFE 写法 
(function () { var tmp = 0; }());



// 块级作用域写法
{ let tmp = 0; }

函数提升

函数提升与变量提升效果一致,但JavaScript只有函数声明语句才存在函数提升.

源代码:

console.log(msg1); // function msg1() {};
console.log(msg2); // undefined
function msg1() {}
var msg2 = function() {}

JavaScript解析器的解析流程:

function msg1() {}; // 函数提升,整个代码块提升到文件的最开始
console.log(msg1);
console.log(msg2);
var msg2 = function() {}

参考来源:

深入理解闭包系列第三篇——IIFE

ECMAScript 6 入门

任务一:零基础JavaScript编码(一)