作用域、上下文、this指向

this

词法作用域 和 动态作用域

  • 词法作用域(静态作用域): 变量定义在哪就在哪,和函数的调用无关。
  • 动态作用域: 函数执行时决定变量作用域
/**
 * 1.分析:如果JS为静态作用域,先找getName函数内是否有局部变量name; 无,找函数书写位置的上层:name = "小丽"。 打印应为 "小丽"
 * 2.分析:如果JS为动态态作用域,先找getName函数内是否有局部变量name; 无,找调用该函数的作用域changeIt()。打印应为:"老王"
 * 3.JS为静态作用域,所以打印"小丽"
*/
let name = "小丽"
function getName() {
    console.log(this.name)
}
function changeIt() {
    let name = "老王"
    getName()
}
changeIt()

作用域链

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

//在当前执行作用域内未找到变量,顺着作用域链向上找

执行上下文

  • js引擎分析和执行代码是一段一段的,当执行一个函数时,会有一个准备阶段(即提供代码运行的环境),这个就叫执行上下文。

顺序执行

var foo = function () {
    console.log('foo1');
}
foo();  // foo1
var foo = function () {
    console.log('foo2');
}
foo(); // foo2

变量、函数提升

console.log(add2(1,1)); //输出2
function add2(a,b){
    return a+b;
}
console.log(add1(1,1));  //报错:add1 is not a function
var add1 = function(a,b){
    return a+b;
}
// 用函数语句创建的函数add2,函数名称和函数体均被提前,在声明它之前就使用它。
// 但是使用var表达式定义函数add1,只有变量声明提前了,变量初始化代码仍然在原来的位置,没法提前执行。

this指向

  1. 直接调用函数。
  2. 隐式调用。
  3. Class 和 new
  4. 显式改变this指向call(arg,a,b,c)/applay(arg,[a,b,c])/bind(arg)()

直接调用函数-----this指向window

function sun(){
    console.log(this)  //指向window
}
sun()

隐式绑定 ---- 直接指向调用函数的上一级

function thisFun(){
    console.log(this.a) 
}
const obj = {
    a:"nnn",
    fn:thisFun
}
obj.fn() //指向obj

Class和new ---- 指向生成的实例

function NewObj(){
    this.a = "ddd";
    this.b = "kkk"
    console.log(this,"this") //NewObj {a: 'ddd', b: 'kkk'} 'this'
}
let obj = new NewObj() 
console.log(obj) // //NewObj {a: 'ddd', b: 'kkk'} 
// new 关键字做了哪些工作
//1.创建一个对象;
//2.这个对象的原型指向它的构造函数;
//3.实现了这个函数;
//  如果这个函数有返回值,且返回值为对象,则返回该对象
//  如果这个函数有返回值,且返回值为非对象,返回要创建的对象
//  如果这个函数没有返回值,返回要创建的对象

显式改变this

  • call(arg, a, b, c)
  • applay(arg, [a,b,c])
  • bind(arg)()
实现一个applay
Function.prototype.newApplay = function(content){
    if(typeof this !== "function"){
        new TypeErro("不是一个函数")
    }
    content = content || window
    content.fn = this;
    let result = arguments[1] ? content.fn(...arguments[1]) : content.fn()
    delete content.fn 
    return result
}
实现一个bind
Function.prototype.newBind = function(){
    if(typeof this !== "function"){
        new TypeErro("不是一个函数")
    }
    let _this = this;
    let list = Array.prototype.slice.call(arguments)
    let newThis = list.shift()
    return function(){
        _this.newApplay(newThis,list)
    }  
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值