在全局/私有上下文中:带VAR和不带VAR的区别

在介绍区别以前,咱们先来看下解决这个需求的两种方式:javascript

  • 需求:验证:name或者age是否是obj的属性
var obj = {
    name: '小芝麻'
};
复制代码

方法一:基于判断属性值是否为undefined来验证是否有这个属性(不专业方案)java

if (obj.name !== undefined) {
    // OBJ中存在这个属性
}
if (obj['age'] === undefined) {
    // OBJ不存在这个属性
}
复制代码

方法二:基于检测符 in 来检测当前属性是否属于这个对象 =>语法: 属性名 in 对象(专业方案)node

if ('age' in obj) {
    // AGE是OBJ属性返回TRUE,不是它的属性返回FALSE
}
复制代码

在讲解全局执行上下文中:带VAR不带VAR的区别,咱们须要先了解全局对象和全局变量对象的区别浏览器

思惟导图

1、全局对象和全局变量对象的区别

以前咱们说过浏览器想要把代码执行就须要先有个执行环境栈ECStack;函数

与此同时也会建立一个全局对象GO;和其余的引用类型值同样,也存储在堆内存中,有一个十六进制的空间地址; 这里存储了不少内置的属性和方法;ui

  • 执行环境栈ECStack中有个window,让window指向这个全局对象的空间地址;
  • 咱们平时用的alert("xxx")的方法,全称:window.alert(...),只不过咱们平时省略了window;

一、全局对象

  • 全局对象:
    • 浏览器默认会自带不少供JS调取使用的内置API,这些属性方法都在GO中存储着,在浏览器端,把GO对象赋值给window,在node端把GO赋值给了global

咱们在控制台详细输出window,看一下;spa

这些就是咱们的全局对象中的内容

二、全局变量对象

全局变量对象:3d

  • 当全局代码执行过程当中,会声明一些变量,这些变量存储在全局变量对象VO

总结:综上所属,咱们知道:

  • 全局对象GO:是浏览器天生自带的存储属性和方法的堆,是一个对象;
  • 全局变量对象VO:是咱们本身写代码建立的变量要存储的地方;是栈内存;

彻底是两个不一样的东西 code

2、全局执行上下文中:带VAR不带VAR的区别

“在全局执行上下文中”,带VAR不带VAR定义值是两套不一样的机制cdn

  • 带VAR是建立一个全局变量,存放在全局变量对象VO(G)
  • 不带VAR建立的不是变量,而是全局对象GO(global object)的一个属性

知道了上面的内容,咱们来用例题分析一下:

var n = 100;
console.log(n);
console.log(window.n);
m = 200;
console.log(m);
console.log(x);
复制代码

总结:

全局上下文中:

  • 基于VAR建立变量,会给VO(G)GO中各自存储一份,
  • 不带VAR的,只是给GO设置一个属性而已;
  • 当咱们输出这个变量值的时候,首先看是否为全局变量,是则输出全局变量的值,若是不是,则在看是否为全局对象的属性,若是再不是,则报错!!

3、私有执行上下文中:带VAR不带VAR的区别

  • 一、带VAR的状况

    在函数里:var x=100;

    • 在私有上下文的AO(FN)变量对象中声明一个x的私有变量(x是当前上下文的私有变量,和上下文之外没有必然联系)
  • 二、不带VAR的状况

    在函数里: y=200;

    • 一、浏览器发现y不是私有变量,则向其上级上下文中查找(按照SCOPE-CHAIN(做用域链,咱们下一篇文章会说)查找),若是上级也没有则继续查找…一直到EC(G)全局上下文为止,找到哪一级,就是哪一级的变量
    • 二、若是找到全局也没有,则给GO(window)设置一个属性:window.y=200

4、全局和私有上下文中带var的区别;

  • 全局执行上下文中:基于VAR建立变量,会给VO(G)GO中各自存储一份;
  • 私有执行上下文中:只在私有变量对象AO中建立了变量,没有给window添加属性;

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(); //=>'哈哈哈'
复制代码