提升(Hoisting)
其实主要是为了厘清 JavaScript 的运作所提出的观念,在 ECMAScript 并未提出这个专有名词,而所谓的提升,就是先将函式
与变数宣告
先提到程序码最上面的动作,再接着执行程序码
JavaScript 会在执行环境中运行程序码,而在建立一个执行环境时可以分为两个阶段:
undefined
在创造环境阶段优先把函式与变数的记忆体空间准备好,就叫做
提升 Hositing
同上面所述,在创造阶段时,会将程序码中所有变数先提到最前面,并在记忆体中预留空间给变数後,系统会先给予一个 undefined
的初始值,等到了执行阶段,会依序执行剩下的程序码,这时候才会赋予变数值,范例如下:
var nickName = 'Carol';
console.log(nickName); // Carol
// 1. 创造阶段
// 先宣告变数 nickName,在记忆体中预留空间,预设值为 undefined
var nickName;
// 2. 执行阶段
// 赋予变数 nickName 值
nickName = 'Carol';
// 显示变数 nickName 值
console.log(nickName); // Carol
第一个 console.log(nickName);
在创造阶段中,记忆体已预留空间给 变数 nickName
,但还未赋予值,系统先给予一个预设值 undefined
,所以显示 undefined
第二个 console.log(nickName);
到了执行阶段,程序码会依序执行,所以到了第二个 console.log
,已赋予 变数 nickName
一个值,显示 Carol
console.log(nickName); // undefined
var nickName = 'Carol';
console.log(nickName); // Carol
// 1. 创造阶段
// 先宣告变数 nickName,在记忆体中预留空间,预设值为 undefined
var nickName;
// 2. 执行阶段
// 显示变数 nickName 值
console.log(nickName); // undefined
// 赋予变数 nickName 值
nickName = 'Carol';
// 显示变数 nickName 值
console.log(nickName); // 'Carol'
因 变数 nickName
没被建立或是宣告,所以系统找不到此变数,故显示错误讯息 Uncaught ReferenceError: nickName is not defined
console.log(nickName);
// Uncaught ReferenceError: nickName is not defined
undefined
与is not defined
差异可在 [Day6] 'undefined' vs 'not defined' 查看更多内容
关於函式的提升,首先我们要了解函式陈述式与函式表达式
函式陈述式又称为具名函式,他会直接给函式一个名子,并可直接利用此名子呼叫函式,而在创造阶段时,函式陈述式优先,他会在记忆体中将函式陈述式的所有内容做保留
function fn() {
// ...
}
fn();
// 1.创造阶段
function fn() {
// ...
}
// 2.执行阶段
fn();
fn();
var nickName = 'Carol';
function fn() {
console.log('我的昵称叫 Carol');
}
var nickName = 'Mary';
fn();
// 1.创造阶段
function fn() {
console.log('我的昵称叫 Carol');
}
// 2.执行阶段
fn();
函式表达式可以将匿名函式或具名函式赋予至一个变数上。而函式表达式并不会像函式陈述式一样,在创造阶段就已经被记忆体保留空间,只会在创造阶段时将此变数在记忆体中保留空间,直到执行阶段才会将函式表达式赋予给此变数,所以若要利用函式表达式,就必须等函式已经赋予到变数上,才能运行此函式,因此只有函式陈述式会提升,而函式表达式则不会
若未定义函式名称则为匿名函式,反之则为具名函式
var fn = function () {
// ...
}
fn();
// 1.创造阶段
var fn;
// 2.执行阶段
fn = function () {
// ...
}
fn();
console.log(fn); // undefined
var fn = function () {
console.log('我的昵称叫 Carol');
}
console.log(fn); // ƒ () { console.log('我的昵称叫 Carol'); }
fn(); // 我的昵称叫 Carol
// 1.创造阶段
var fn;
// 2.执行阶段
console.log(fn); // undefined
fn = function () {
console.log('我的昵称叫 Carol');
}
console.log(fn); // ƒ () { console.log('我的昵称叫 Carol'); }
fn(); // 我的昵称叫 Carol
因匿名函式还未赋予到变数上,所以还不能运行此函式,故会报错
fn();
var fn = function () {
console.log('我的昵称叫 Carol');
}
// Uncaught TypeErroe: fn2 is not a function
// 1.创造阶段
var fn;
// 2.执行阶段
fn();
// Uncaught TypeErroe: fn2 is not a function
// 报错,所以下面的程序码不会继续执行
// fn2 = function () {
// console.log('我的昵称叫 Carol');
// }
fn(); // 第 1 名
function fn() {
console.log('第 1 名');
}
fn(); // 第 1 名
var fn = function () {
console.log('第 2 名');
}
fn(); // 第 2 名
// 1.创造阶段
function fn() {
console.log('第 1 名');
}
var fn;
// 2.执行阶段
fn(); // 第 1 名
fn(); // 第 1 名
fn = function () {
console.log('第 2 名');
}
fn(); // 第 2 名
fn(); // 第 1 名
var fn = function () {
console.log('第 2 名');
}
fn(); // 第 2 名
function fn() {
console.log('第 1 名');
}
fn(); // 第 2 名
// 1.创造阶段
function fn() {
console.log('第 1 名');
}
var fn;
// 2.执行阶段
fn(); // 第 1 名
fn = function () {
console.log('第 2 名');
}
fn(); // 第 2 名
fn(); // 第 2 名
後面函式覆盖掉前面
fn(); // 第 2 名
function fn() {
console.log('第 1 名');
}
fn(); // 第 2 名
function fn() {
console.log('第 2 名');
}
fn(); // 第 2 名
// 1.创造阶段
function fn() {
console.log('第 1 名');
}
function fn() {
console.log('第 2 名');
}
// 2.执行阶段
fn(); // 第 2 名
fn(); // 第 2 名
fn(); // 第 2 名
fn(); // undefined
function fn() {
console.log(nickName);
}
var nickName = 'Carol';
fn(); // Carol
// 1.创造阶段
function fn() {
console.log(nickName);
}
var nickName;
// 2.执行阶段
fn(); // undefined
nickName = 'Carol';
fn(); // Carol
fn();
function fn() {
if (rank) {
rank = 2;
}
}
console.log(rank); // undefined
var rank = 1;
console.log(rank); // 1
fn();
console.log(rank); // 2
// 1.创造阶段
function fn() {
if (rank) {
rank = 2;
}
}
var rank;
// 2.执行阶段
fn();
console.log(rank); // undefined
rank = 1;
console.log(rank); // 1
fn();
console.log(rank); // 2
变数在宣告时,有一特性,如该变数已存在,则不会修正他 (只能用 var
,因 let
与 const
不能重复宣告)
var a = 1;
var a;
console.log(a); // 1
前言 延续着上篇的介绍,这篇要来介绍visualVM的Sampler页签 Sampler 这边我延续...
今天跑去面试新工作和准备下一阶段面试,十一点才想到要写,所以就意思意思一下XD,之後会回来补齐的Q...
大家好,我是西瓜,你现在看到的是 2021 iThome 铁人赛『如何在网页中绘制 3D 场景?从 ...
1.函式基础 我们经常使用alert();这可以叫出一个警告视窗,alert就是一个系统预先写好的程...
失控玩家在线看 烂番茄指数 81%,观众指数 95%,《脱稿玩家》叫好又叫座成为 2021 今年好莱...