当浏览器加载html页面的时候,会先提供一个供全局JS代码执行的环境,称为全局作用域
(global/window)
变量在预解析时仅提前声明
console.log(num); //undefined
var num = 12;
console.log(num); //12
if(false){
var a = 13;
}
console.log(a); //undefined
预解析时仅var num; 告诉浏览器在全局作用域中有一个num变量了,此时还未定义
不管if条件成立不成立,里面有var声明都进行预解析
if(!("num" in window)){
var num = 12;
}
//条件成立才会赋值
console.log(num); //undefined
showMsg(); //这是第二个函数
function showMsg(){
alert("这是第一个函数");
}
showMsg(); //这是第二个函数
function showMsg(){
alert("这是第二个函数");
}
函数执行时先创建自己的私有作用域,然后如果有形参,先给形参赋值,再进行私有作用域的预解析,再代码从上至下执行
私有变量:在私有作用域中声明的变量和函数的形参
var fn = function(){};在JS预解析时,在匿名函数表达式中只预解析等号(=)左边的,右边的作为值不参与预解析.即var fn;
fn(); //报错 TypeError: fn is not a function //该项不为函数,不能执行
var fn = function(){
console.log("ok");
}
自执行函数定义的function在全局作用域下是不进行预解析的,当代码执行到这个位置时,定义和执行一起完成
函数体中return下面的代码虽然不再执行了,但是也会预解析;return后面跟着的都是返回值,所以不进行预解析
function fn(){
console.log(num);
return function(){}; //该function作为返回值不进行预解析
var num = 12; //该num作为声明变量进行预解析
}
fn();
带var的变量可以进行预解析,在赋值之前执行不会报错
不带var的变量是不能进行预解析的,在赋值之前执行会报错
console.log(num); //报错:num is not defined
num = 12;
num = 12;
console.log(num); // 12 window.num
全局作用域中增加了一个全局变量num,相当于给window增加了一个num属性,值为12
注:JS中在不做任何特殊情况处理下,上面的代码报错,下面的代码都不再执行
在JS中,变量名和函数名重复了,是冲突情况;在预解析时如果名字已经声明过了不需要重新声明,但会重新赋值
var fn = 12;
function fn(){...}
//这两个fn是一个名字,最终只能保留一个值,最终fn为变量
fn();
function fn(){console.log(1)}
fn();
var fn = 12;
fn();
function fn(){console.log(2)}
fn();
console.log(total); // undefined
var total = 0;
function fn(num1,num2){
console.log(total); //undefined
var total = num1+num2;
console.log(total); //300
}
fn(100,200);
console.log(total); //0
var num = 10;
function fn(){
var num = 100;
return funciton(){
console.log(num);
}
}
var f = fn();
f();
~function(){
var num = 1000;
f();
}();
f()的值和执行环境无关,和定义环境有关
字符串
var obj1 = {"name":"张三"};
var obj2 = obj1;
obj1 = null;
obj2 = null;
全局作用域
属于不销毁作用域,只有当页面关闭的时候才会销毁 函数执行返回了一个引用数据类型的值,并且在函数的外面被一个其他东西接收了则不销毁
function fn(){
var num = 100;
return function(){
console.log(num);
}
}
var f = fn(); //返回值被f接收,fn不能被销毁
自执行函数形成的私有作用域在这种情况下也不销毁
var oDiv = document.getElementById('div1');
~function(){
oDiv.onclick = function(){
}
}();
注:通过DOM方法获取的元素、元素集合都是对象数据类型的值
var oDiv = document.getElementById('div1');
不立即销毁:fn返回的函数没有被其他东西占用,但还需要执行一次
,所以暂时不能销毁,当返回的值执行完后浏览器在空闲时间把它销毁
function fn(){
var num = 12;
return function(){
}
}
fn()(); //表示执行函数fn,再执行返回值的函数
函数执行首先看函数名前有没有点,有的话前边是谁this就是谁,没有的话就是window
function fn(){
console.log(this);
}
var obj = {fn:fn};
fn(); // 方法名前没有点
obj.fn(); //方法名前有点
function sum(){
fn();
}
sum(); //与执行环境无关
var aa = {
sum:function(){
fn();
}
}
aa.sum(); //this --> window与执行环境无关
自执行函数的this永远是window
给元素的某一事件绑定方法,当事件触发的时候,执行对应方法时当前this指该元素
document.getElementById('div1').onlick = fn; //this ==> #该方法
document.getElementById('div1').onlick = function(){
//该方法的this指#div1
fn(); //该方法的this依然是window
}