什么是执行上下文?
执行上下文:就是在函数即将执行前,所进行的一些准备工作。也叫作执行上下文环境。准备工作就是指创建函数作用域和创建局部变量对象等。
变量提升:使用var关键字声明的变量,会在所有代码执行之前被声明
cosole.log(a);
var a=;
这里会打印输出undefined
函数提升:使用函数声明形式创建的函数function(){}他会在所有代码之行前被创建
先执行变量提升,在执行函数提升,最后在进行赋值操作。
执行上下文分为:全局执行上下文和函数执行上下文
全局执行上下文:在执行全局代码之前将window确定为全局执行上下文;
对全局数据进行预处理;
var定义的变量==》undefined ,添加为window的属性;
function声明的全局函数==》fn,添加为window的属性;
this==>赋值为window;
开始执行全局代码;
当函数上下文执行的时候,可以看成一个对象,对象拥有属性:
executionContextObj = {
variableObject : {}, // 变量对象,里面包含Arguments对象,形参,函数和局部变量
scopeChain : {},// 作用域链,包含上下文所有变量对象的列表
this : {}// 上下文中this的指向
}
执行上下文的工作原理:
//变量声明
var a1 = 9,
a2 = 8,
a3 = "sss",
b1 = {name:"xixi"};
//函数调用
a1 = f1(a1,a2);
//函数声明
function f1(a,b){
//f1函数的执行上下文
/*
1.扫描参数: a = 9 b = 8
2.扫描函数声明 f2 = function(){}
3.扫描变量声明 t = undefined , m = undefined , i = undefined
*/
var t = 0,
m = 10;
for(var i=0;i<a;i++){
console.log(i);
}
function f2(){
console.log("f2");
}
return a+b;
}
1.创建一个后进先出的执行上下文的栈;
2.接着创建全局的执行上下文,并压入栈中;
3.当调用函数时,会创建函数的执行上下文,并压入栈中;
4.当函数执行完毕,位于栈顶的函数执行上下文被弹出,并执行新的位于栈顶的执行上下文;
执行上下文分为两个阶段:
1.创建阶段(将变量,函数声明以及函数参数组成一个活动对象VO(可变对象)(变量对象)) 创建VO——》填充函数参数——》填充函数声明(冲突覆盖)——》填充变量声明(冲突忽略)
2.执行阶段(解释代码);
因此,变量和函数声明会被提前,并且函数表达式并不会被VO(相当于函数的激活对象AO)记录
作用域链
什么是作用域链:所谓作用域链,就是内部上下文所有变量对象(包括父变量对象)的列表。主要用于变量查询
关于高阶函数
在JS里,函数作用一等公民,可以作为参数来进行传递,也可以作为函数的返回值来返回
接受一个或多个函数作为输入
输出一个函数
高阶函数是对其他函数进行操作的函数,可以将它们作为参数传入,或者返回。即高阶函数是一个接受函数作为参数传递或者将函数作为返回值输出的函数
参数传递
把函数作为参数传递,代表可以抽离出一部分容易变化的业务逻辑。我们常见的场景就是回调函数,在ajax异步请求的应用中,回调函数的使用非常频繁
回调函数:
var getUserInfo = function (userId, callback) {
$.ajax('http://xx.com/getUserInfo?'+userId, function (data) {
if(typeof callback === 'function') {
callback(data);
}
})
}
getUserInfo(123, function(data) {
alert(data.userName)
})
数组排序:
// 从小到大
var values = [1,4,7,9];
values.sort(function(a, b) {
return a - b;
});
console.log(values);
// 从大到小
values.sort(function(a, b) {
return b - a ;
})
console.log(values);
返回值输出
isType函数:
{
var isString = function(obj) {
return Object.prototype.toString.call(obj) === '[object String]';
}
var isArray = function(obj) {
return Object.prototype.toString.call(obj) === '[object Array]';
}
var isNumber = function (obj) {
return Object.prototype.toString.call(obj) === '[object Number]';
}
console.log(isString('123'));
console.log(isArray([1,2,3]));
console.log(isNumber(123));
}
闭包
1.密闭的容器,类似set,map容器,存储数据的
2.闭包是一个对象,存放数据 key:value
闭包优点:
延长外部函数局部变量生命周期
闭包缺点:
长时间占用容易内存泄露
//简单闭包
function out(){
var a = 1;
function inner() {
console.log(a);
}
inner()
}
out()
//稍微复杂的闭包
function fun(a,b) {
//let a = 0
console.log(b)
return {
fun:function (m) {
//let m = 1
return fun(m,a)
}
}
}
/*let a = fun(0)
a.fun(1)
a.fun(2)
a.fun(3);//undefined 0 0 0*/
// let b = fun(0).fun(1).fun(2);//undefined 0 1
let c = fun(0).fun(1);//undefined 1
c.fun(2)
c.fun(3)
闭包和面向对象设计
const Test = function(){
let value = 0;
return {
call : function(){
value++;
console.log(value);
}
}
}
const test = new Test();
test.call(); // 1
test.call(); // 2
test.call(); // 3
面向对象:
const test = {
value: 0,
call: function () {
this.value++;
console.log(this.value);
}
}
test.call(); // 1
test.call(); // 2
test.call(); // 3