什么是作用域?
作用域是运行时代码中某些特定部分中 变量、函数、对象的可访问性,他决定了区块代码中变量和其他资源的可见性。
在ES6中JS新增了块级作用域,我们可以通过新增命令let和const来体现.
全局作用域
特点:
- 在代码中任意地方都能访问到的对象拥有全局作用域
- 在全局作用域中定义的变量可以在任何地方使用
- 全局作用域在页面打开时创建,在页面关闭时销毁
情况一:所有未定义直接赋值的自动声明为拥有全局作用域
function fu1() { a = '未定义直接赋值的变量'; var b = '内层变量' } fu1(); console.log(a); //未定义直接赋值的变量 // console.log(b); //b is not defined //注意:如果一个变量在声明的时候没有使用关键字 //例如:num = 10,此时这个变量无论写在哪里都是全局变量
情况二:最外层函数和最外层函数外面定义的变量拥有全局作用域
var a = '最外层变量'; function fu2() { //最外层函数 var b = '最外层函数的内层变量' function fu3() { //内层函数 var c = '内层函数的内部变量' } } console.log(a);//最外层变量 // console.log(b); // b is not defined fu1() fu2() // console.log(c);//c is not defined
情况三:所有window对象的属性拥有全局变量(所有浏览器环境的全局变量,都是window对象的属性)
var e = 1; console.log(window.e) //1 //window.name属性用于设置当前浏览器窗口的名字。 //它有一个特点,就是浏览器刷新后,该属性保持不变。 //所以,可以把值存放在该属性内,然后跨页面、甚至跨域名使用。 //当然,这个值有可能被其他网站的页面改写。 window.name = "hello world"; console.log(window.name);//hello world
局部作用域
声明在函数内部的变量,和全局作用域相反,局部作用域一般只在固定的代码片段内可以访问
实例
function f1(){ let a = 1; console.log(a);//1 } f1() console.log(a);//a is not defined
块级作用域
实例一:if
//if if () { let a = 1 console.log(a); //1 } console.log(a); // a is not defined
实例二:for
//for for (let i = 0; i < 5; i++) { console.log('循环内'+ i); } console.log('循环外'+ i); // i is not defined
作用域链
特点:
-
默认情况下,代码处于全局作用域(0级链),当声明一个函数之后就会开辟一个局部作用域(1级)。而函数里面又可以声明一个函数,又会形成新的作用域(2级),以此类推形成的结构称之为作用域链
-
变量访问规则:就近原则
实例
// [变量访问规则:就近原则] //当你在一个作用域访问变量的之后,首先会看当前作用域有没有声明。 //如果有则访问。没有则往上级作用域查找,有没有声明。 //直到作用域最顶端0级,如果还没有找到,则程序报错。 //0级 let a = 1 function f1() { //1级 let a = 2; console.log(a); //2级 function f2() { let a = 3; console.log(a); } f2() } f1() console.log(a);
最终输出结果:
匿名函数
语法:
let f2 = function () { console.log('2'); //2 }
自执行匿名函数
语法:
// 自执行语法:(匿名函数)() (function () { let a = 10 console.log('666'); // 666 })();
什么是this?
-
this是一个使用在作用域内部(块级作用域、函数作用域、全局作用域)的关键字。
-
this关键字是函数运行时自动生成的一个内部对象,只能在函数内部使用,总指向调用它的对象
-
全局作用域中很少使用,大部分在函数内部使用
this指向
特点
-
根据运行时的不同,this指向的对象有所区别
-
在绝大多数情况下,函数的调用方式决定了this的值
-
浏览器环境/全局环境下使用this: this指向window对象
console.log( this ); // window
console.log( this === window ); //true
在函数中使用this:
//在函数中使用this:
//不管函数怎么定义,不管函数在哪定义,只看函数的调用(箭头函数除外)。
//普通函数(直接调用/全局调用):this指向window
//函数名()
function fn() {
console.log(this); //window
}
fn()//普通调用,this指向window
//定时器函数:this指向window
// setTimeout( function(){},0)
// setInterval(function(){},0)
setTimeout(fn,0)//把fn函数当作定时器处理函数使用
//自执行函数: this指向window
//(function(){})()
//对象调用函数:this指向的是xxx对象
//xxx.函数名():
// Math.random( ):
//问:a.b.c()函数中的this指向是? 答:a.b
var obj = {
//把fn存储的地址赋值给了obj的f成员
//从现在开始obj.f和全局变量的fn指向同一个函数空间
f:fn,
name:'我是obj对象'
}
obj.f() //对象调用,this指向obj。
setTimeout(obj.f,0)//把obj.f函数当作定时器处理函数使用
//事件处理函数: this指向的是事件源(绑定在谁身上的事件)
//xxx.onclick = function(){}
//xxx.addEventListener('',function(){})