在介绍区别之前,我们先来看下解决这个需求的两种方式:
- 需求:验证:
name
或者age
是不是obj
的属性
var obj = {
name: '小芝麻'
};
复制代码
方法一:基于判断属性值是否为undefined
来验证是否有这个属性(不专业方案)
if (obj.name !== undefined) {
// OBJ中存在这个属性
}
if (obj['age'] === undefined) {
// OBJ不存在这个属性
}
复制代码
方法二:基于检测符 in
来检测当前属性是否属于这个对象 =>语法: 属性名 in 对象
(专业方案)
if ('age' in obj) {
// AGE是OBJ属性返回TRUE,不是它的属性返回FALSE
}
复制代码
在讲解全局执行上下文中:
带VAR
和不带VAR
的区别,我们需要先了解全局对象和全局变量对象的区别
思维导图
一、全局对象和全局变量对象的区别
之前我们说过浏览器想要把代码执行就需要先有个
执行环境栈ECStack
;与此同时也会创建一个
全局对象GO
;和其他的引用类型值一样,也存储在堆内存中,有一个十六进制的空间地址; 这里存储了很多内置的属性和方法;
- 在
执行环境栈ECStack
中有个window
,让window
指向这个全局对象的空间地址;- 我们平时用的
alert("xxx")
的方法,全称:window.alert(...)
,只不过我们平时省略了window
;
1、全局对象
全局对象:
- 浏览器默认会自带很多供
JS
调取使用的内置API
,这些属性方法都在GO
中存储着,在浏览器端,把GO
对象赋值给window
,在node
端把GO
赋值给了global
- 浏览器默认会自带很多供
我们在控制台详细输出window
,看一下;
这些就是我们的全局对象中的内容
2、全局变量对象
全局变量对象:
- 当全局代码执行过程中,会声明一些变量,这些变量存储在
全局变量对象VO
中
总结:综上所属,我们知道:
全局对象GO
:是浏览器天生自带的存储属性和方法的堆,是一个对象;全局变量对象VO
:是我们自己写代码创建的变量要存储的地方;是栈内存;
完全是两个不同的东西
二、全局执行上下文中:带VAR
和不带VAR
的区别
“在全局执行上下文中”,
带VAR
和不带VAR
定义值是两套不同的机制
带VA
R是创建一个全局变量,存放在全局变量对象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
设置一个属性而已;- 当我们输出这个变量值的时候,首先看是否为全局变量,是则输出全局变量的值,如果不是,则在看是否为全局对象的属性,如果再不是,则报错!!
三、私有执行上下文中:带VAR
和不带VAR
的区别
- 1、带
VAR
的情况
在函数里:
var x=100
;
- 在私有上下文的
AO(FN)
变量对象中声明一个x
的私有变量(x
是当前上下文的私有变量,和上下文以外没有必然联系)
- 2、不带
VAR
的情况
在函数里:
y=200
;
- 1、浏览器发现
y
不是私有变量,则向其上级上下文中查找(按照SCOPE-CHAIN
(作用域链,我们下一篇文章会说)查找),如果上级也没有则继续查找…一直到EC(G)
全局上下文为止,找到哪一级,就是哪一级的变量- 2、如果找到全局也没有,则给
GO(window)
设置一个属性:window.y=200
四、全局和私有上下文中带var
的区别;
- 全局执行上下文中:基于
VAR
创建变量,会给VO(G)
和GO
中各自存储一份; - 私有执行上下文中:只在私有变量对象
AO
中创建了变量,没有给window
添加属性;
五、例题
1、输出结果
/*
* 全局上下文中的变量提升
* 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
复制代码
2、输出结果
/*
* 全局上下文中的变量提升(最新版本浏览器中)
* 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(); //=>'哈哈哈'