JS基础:一篇文章搞懂执行上下文

1、可执行代码的分类

可执行代码(executable code):执行可执行代码的时候,会创建对应的执行上下文。

  • 全局上下文
  • 函数上下文
  • eval(几乎不用)

2、执行上下文栈

执行上下文栈(FILO)

例1:

var scope = 'global scope';
function checkscope() {
    var scope = 'local scope';
    function f (){
        return scope;
    }
    return f();
}
checkscope();

执行上下文栈变化
在这里插入图片描述
例2:

var scope = 'global scope';
function checkscope() {
    var scope = 'local scope';
    function f (){
        return scope;
    }
    return f;
}
checkscope()();

执行上下文栈变化
在这里插入图片描述

3、执行上下文3个重要的特点

执行上下文(execution context)

① 变量对象

变量对象:variable object,简称VO。
变量对象是指 上下文中定义的变量和函数的声明。

全局上下文

this指向全局对象,浏览器环境下this指向window。
在JS中,全局VO指代的就是全局对象。

函数上下文

函数中的变量对象也叫活动对象。

执行代码

1、进入执行上下文,分析
2、代码执行

function foo(a){
	var b = 2;
	fucntion c(){};
	var d = function(){};
	b = 3;
	// console.log(e) 报错 没有声明
	e = 'e';
}
foo(1);

分析在这里插入图片描述

② 作用域链(scope chain)

a、什么是作用域

定义变量的区域

b、作用域的分类

静态作用域:例如JS、C,、C++、 Python、Java
动态作用域:例如bash、Pascal、Emacs Lisp

scope.bash文件

 value=1
 function foo(){
    echo $value;
 }

function bar(){
    local value=2;
    foo;
 }
 bar

执行:bash scope.bash
结果:2

c、作用域的类型

  • 全局作用域
  • 函数作用域
  • 模块作用域

c、作用域链

遇到一个变量,先在当前上下文中找VO、再找父级上下文的VO,直到找到全局变量this(window)。这个沿着上下文找到的VO链,叫作用域链。

function foo() {
    function bar (){}
}

// foo的作用域链
foo.[[scope]] = [
	globalContext.VO,
]

// bar的作用域链
bar.[[scope]] = [
	fooContext.VO,
	globalContext.VO,
]

③ this

全局中,this是全局对象,在浏览器中全局对象是widnow。

this指向什么

this指向调用它的内容。‌

全局代码中:this只想全局对象,浏览器环境中全局对象是window;

方法中:this指的是调用该方法的对象;

函数中

  • 函数作为对象的方法被调用:this指向调用该方法的对象
  • 通过call、‌apply或bind方法被调用:this可以指向任意对象
  • 没有明确指定:指向全局对象
闭包

自由变量:能在函数中使用的,但是不属于函数参数和局部变量的变量。
闭包:函数 + 函数里能访问非自身的变量。

function checkscope(){
	var scope = 'local';
	function f(){
		return scope;
	}
	return f;
}
checkscope()();

// f的作用域链
[AO, checkscope.AO, globalContext.VO];
// 虽然checkscope不在执行上下文栈中了,但是f可以通过作用域链访问到scope,这种访问存在内存泄漏的风险

4、传递参数

基本类型按值传递,引用类型按拷贝的地址传递。

5、自定义call、apply、bind、new

Function.prototype.call2 = function (context, ...args) {
    if ((typeof context === 'undefined') || (context === 'null')) {
        context = window;
    }
    let fnSymbol = Symbol();
    context[fnSymbol] = this;
    let fn = context[fnSymbol](...args);
    delete context[fnSymbol];
    return fn;
}
Function.prototype.apply2 = function (context, arr) {
    if ((typeof context === 'undefined') || (context === 'null')) {
        context = window;
    }
    let fnSymbol = Symbol();
    context[fnSymbol] = this;
    let fn = arr ? context[fnSymbol](...arr) : context[fnSymbol]();
    delete context[fnSymbol];
    return fn;
}
Function.prototype.bind2 = function (context, ...arguments) {
	// this就是当前方法
    var _this = this;
    var _arguments = Array.prototype.slice.call(arguments);
    var fBound = function (...args) {
    // this instanceof fBound 构造函数this指向自身
        return _this.apply(this instanceof fBound ? this : context, args.concat(_arguments));
    };
    return fBound;
}

自定义new:objectFactory

const person1 = new Person(1, 2);
const person2 = objectFactory(Person, 1, 2);

function objectFactory(Constructor, ...args) {
	// 新建对象
    var obj = {};
    // 新对象的__proto__ 指向构造函数的prototype
    obj.__proto__ = Constructor.prototype;
    // 构造函数执行结果
    var ret = Constructor.apply(obj, args);
    // 结果是对象就返回接口,否则返回创建的新对象
    return typeof ret === 'object' ? ret : obj;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值