函数执行
1.函数
1.表达式方式创建函数,在变量提升阶段,并不会给函数赋值,这样只有代码执行的过程中,函数赋值后才可以执行(不能在赋值之前执行)
-
符合严谨的执行逻辑
-
真实项目中推荐的方式
//1.不推荐使用 func();//=>ok function func() { console.log('OK'); }
//2. var func = function () { console.log('OK'); }; func();分析步骤: 1.变量提升:var func; (默认值是undefined) 2. func(); 执行 3.相当于 undefined() =>Uncaught TypeError: func is not a function 报错一下代码不在执行
2.匿名函数
为了保证语法的规范性,JS中原本创建的匿名函数,我们最好设置一个名字,但是这个名字在函数外面还是无法使用的,只能在本函数体中使用(一般也不用)
//1.函数内没有return,所以不能暴露给函数外使用,报错后 ,下面代码不在执行
var func = function anonymous() {
// console.log(anonymous); //=>当前这个函数本身
};
// console.log(anonymous);
//=>Uncaught ReferenceError: anonymous is not defined 函数内没有return所以函数不能使用
func();
//2.
var func = function func() {
console.log(func); //=>函数名func本身
};
console.log(func); //=>变量func,存储的值是函数
func();
3.条件判断中包含函数执行
在当前执行上下文中,不管条件是否成立,变量提升是有效的
/*
* 全局上下文中的变量提升:
* [VO(G) 全局变量对象]
* var n; 不论IF条件是否成立
*/
console.log(n); //=>undefined
if (1 > 1) { //=>条件不成立
var n = 100;
}
console.log(n); //=>undefined
/*
* 全局上下文中的变量提升:
* [VO(G) 全局变量对象]
* [IE 10及以前以及谷歌等浏览器低版本状态下]
* function func(){ ... } 声明+定义都处理了
*
* [最新版本的浏览器中,机制变了]
* function func; //=>用判断或者循环等包裹起来的函数,在变量提升阶段,不论条件是否成立,
此处只会先声明
*/
console.log(func); //=>undefined
if (1 === 1) {//=>1.此时条件成立,进来的第一件事情还是先把函数定义了(迎合ES6中的块作用域)
//=>2.func=function(){ .... }
console.log(func); //=>函数本身
function func() {
console.log('OK');
}
console.log(func); //=>函数本身
}
console.log(func); //=>函数本身
4.检测对象中是否包含某个属性名
-
第一种检测方式
var obj = { name: 'Hello' };
要求:验证:name或者age是不是obj的属性
// 1.基于判断属性值是否为undefined来验证是否有这个属性 if (obj.name !== undefined) { // OBJ中存在这个属性 } if (obj['age'] === undefined) { // OBJ不存在这个属性 }
// 2.基于检测符 in 来检测当前属性是否属于这个对象 =>语法: 属性名 in 对象
if ('age' in obj) { // AGE是OBJ属性返回TRUE,不是它的属性返回FALSE }
5.案例
/*
* 全局上下文中的变量提升
* var a;
* ->给VO(G)中新增一个全局变量 a
* ->给GO中新增一个属性 a
* ->默认值都是 undefined
*/
console.log(a); //=>undefined
if (!('a' in window)) {
// 'a' in window 检测a是否为window的一个属性 =>TRUE
// !true => FALSE 条件不成立
var a = 13;
}
console.log(a); //=>undefined
/*分析:
* 全局上下文中的变量提升(最新版本浏览器中)
* function fn;
* ->VO(G)中存在一个fn全局变量
* ->GO中存在一个fn属性
*/
console.log(fn); //=>undefined
fn();//=> undefined() =>Uncaught TypeError: fn is not a function
//=>JS中,一但当前代码报错,那么下面的代码都不会再执行了
if ('fn' in window) {
fn();
function fn() {
console.log('哈哈哈');
}
}
fn();
/*分析:
* 全局上下文中的变量提升(最新版本浏览器中)
* function fn;
* ->VO(G)中存在一个fn全局变量
* ->GO中存在一个fn属性
*/
console.log(fn); //=>undefined
if ('fn' in window) { //=>TRUE
//=> 进来第一件事情:给FN赋值 fn=function(){ ... }
fn(); //=>'哈哈哈'
function fn() {
console.log('哈哈哈');
}
}
fn(); //=>'哈哈哈'
//分析:
// 分析:浏览器有一个特征:做过的事情不会重新再做第二遍(例如:不会重复声明)
/*
* 全局上下文中的变量提升
* fn = function(){ 1 } 声明+定义
* = function(){ 2 }
* var fn; 声明这一步不处理了(已经声明过了)
* = function(){ 4 }
* = function(){ 5 }
* 结果:声明一个全局变量fn,赋的值是 function(){ 5 }
*/
fn(); //=>5
function fn(){ console.log(1); } //=>跳过(变量提升的时候搞过了)
fn(); //=>5
function fn(){ console.log(2); } //=>跳过
fn(); //=>5
var fn = function(){ console.log(3); }
//=>var fn; 这一步跳过,但是赋值这个操作在变量提升阶段没有搞过,需要执行一次 => fn = function(){ 3 }
fn(); //=>3
function fn(){ console.log(4); }
//=>跳过
fn(); //=>3
function fn(){ console.log(5); }
//=>跳过
fn(); //=>3
/*
* 高版本浏览器
* 全局上下文中变量提升:没有
*/
f=function (){return true;};//=>给GO中设置一个属性 f = function () {return true;}
g=function (){return false;};//=>给GO中设置一个属性 g = function () {return false;}
(function () {
/*
* 自执行函数执行,形成一个私有的执行上下文
* [变量提升]
* function g;
* 高版本浏览器中,在判断和循环中的函数,变量提升阶段只声明不定义
*
* 条件解析:
* g() ;
* undefined() => Uncaught TypeError: g is not a function
* 下面操作都不在执行了
*/
if (g() && [] == ![]) {
f = function () {return false;}
function g() {return true;}
}
})();
console.log(f());//=>false
console.log(g());//=>false
/*分析:
* 低版本浏览器(包含IE10及以内)
* 全局上下文中变量提升
* 没有
*/
f=function (){return true;};
//给GO中设置一个属性 f = function () {return true;}
g=function (){return false;};
//给GO中设置一个属性 g = function () {return false;}
(function () {
/*
* 自执行函数执行,形成一个私有的执行上下文
* [变量提升]
* function g(){return true;}
*/
// 条件解析:
// g(); //=> 私有的G执行 TRUE
// []==![] => []==false => 0==0 => TRUE
if (g() && [] == ![]) { //=>条件成立
f = function () {return false;}
//f不是自己私有的,则向上查找,属于全局对象中的f,
//=>此处是把全局对象中的 f = function () {return false;}
function g() {return true;}
//跳过(变量提升处理过了)
}
})();
console.log(f()); //=>FALSE
console.log(g()); //=>FALSE 这个G找全局的(函数里面的G是自己私有的)