1.作用域
一般理解指一个变量的作用范围,另外注意js中没有块级作用域
1.1全局作用域
-
全局作用域在页面打开时被创建,页面关闭时被销毁
-
编写在script标签中的变量和函数为全局作用域,页面任何位置都能访问
-
全局作用域中声明的变量和函数会作为window对象的属性和方法保存
-
例:书写以下代码,在浏览器控制台中查看window对象,全局变量的值均可在window对象中找到
<body> <script> var b = 12 var bb = { a: 1990 } </script> </body>
1.2函数作用域
1.调用函数时,函数作用域被创建,函数执行完,作用域销毁
2.每次调用函数都会创建一个新的函数作用域,相互之间是独立的
3.在函数作用域中可以访问全局作用域的变量,函数外部不能访问函数作用域内的变量
4.在函数作用域中访问变量与函数时,会先从自身作用域中寻找,若没找到,再从函数上一级作用域中寻找,直到全局作用域
1.3作用域的深层次理解
1.3.1执行期的上下文
-
当函数代码执行的前期会创建一个执行期上下 文的内部对象AO
-
这个内部的对象是预编译时创建出来的,因为当出次数调用时会先进行预编译
-
在全局代码执行的前期会创建一个执行期的上下文对象GO
1.3.2函数作用域编译
-
创建ao对象 AO{}
-
找形参与变量声明,将形参与形参名当做AO对象的属性名值为UNDEFINED
-
实参形参相统一
-
在函数体里面找函数声明,值赋予函数体
1.3.3预编译的时候做了哪些事情
例子:
function fn (a, c) {
console.log(a)//function a(){}
var a = 123
console.log(a)//123
console.log(c)//function c(){}
function a () { }
if (false) {
var d = 678
}
console.log(d)//undefined
console.log(b)//undefined
var b = function () { }//表达式
console.log(b)//function(){}
function c () { }
console.log(c)//function c(){}
}
fn(1, 2)
-
创建ao对象
//全称:active Object活动对象,保存函数调用时的局部变量,其实AO对象就是函数作用域对象 AO:{}
-
找形参和变量声明,作为ao对象的属性名 值是undefined
AO:{ a:undefined c:undefined d:undefined b:undefined }
-
实参和形参相统一
AO:{ a:undefined -->1 c:undefined -->2 d:undefined b:undefined }
-
找函数声明(不是表达式如:a=function(){}),会覆盖变量的声明
AO:{
a:undefined -->1 -->function a(){}
c:undefined -->2 -->function c(){}
d:undefined
b:undefined
}
- 整个程序实际运行如下
function fn (a, c) {
//第一步找形参和变量声明,作为ao对象的属性名 值是undefined
var a;//undefined
var d;//undefined
var b;//undefined
var c;//undefined
//第二步实参和形参相统一
a = 1
c = 2
//第三步找函数声明,会覆盖变量的声明
a = function a () { }
c = function c () { }
//接下来就按原代码顺序执行
console.log(a)//function a(){}
a = 123
console.log(a)//123
console.log(c)//function c(){}
function a () { }
if (false) {
d = 678
}
console.log(d)//undefined
console.log(b)//undefined
b = function () { }//表达式
console.log(b)//function(){}
function c () { }
console.log(c)//function c(){}
}
fn(1, 2)
1.3.3全局作用域的预编译
-
创建GO对象
-
找变量声明,将变量名作为GO对象的属性名值为undefined
-
找函数声明,值赋予函数体
2.this指向
-
全局作用域或者普通函数中this指向全局对象window。定时器里的this指向window
-
对象中的方法谁调用this指向谁
-
构造函数中this指向构造函数实例
var name = 222
var a = {
name: 111,
say: function () {
console.log(this.name)
}
}
var fun = a.say
fun()//fun.call(window)===222
a.say()//a.say.call(a)===111
var b = {
name: 333,
say: function (fun) {
fun()
}
}
b.say(a.say)//在b.say中调用a.say方法,此时fun()的调用者为window相当于fun.call(window)===222
b.say = a.say//b.say为function(){console.log(this.name)}
b.say()//因为b.say的值已改变所以this指向为b相当于b.say.call(b)===333
2.1箭头函数中的this
-
箭头函数不绑定this关键字,箭头函数中的this指向的是函数定义位置的父执行上下文this,箭头函数内部this值只能通过查找作用域链,同时也不能用作构造函数
-
例如:箭头函数本身所在的对象为obj,而obj的父执行上下文(作用域)为window因此输出为11(obj作用域于window所以箭头函数this指向于window)
var x=11 var obj={ x:22, say:()=>{ console.log(this.x)} } obj.say()//值为11
-
自我理解成:箭头函数的this指向为上一级的上一级的this,例如下例代码:gets的父(上一级)为obj,obj的父(this)为window,所以gets里的this指向为window。而geta中fn的this指向为obj,因为fn的父(上一级)为geta,而geta的父(上一级)为obj因此this指向为obj
var b = 12 var obj = { b: 1990, gets: () => { console.log(this.b) }, geta: function () { var b = 2000; var fn = () => new Date().getFullYear() - this.b return fn() } } obj.gets() console.log(obj.geta())