JS:作用域、作用域链、this

什么是作用域?

作用域是运行时代码中某些特定部分中 变量、函数、对象的可访问性,他决定了区块代码中变量和其他资源的可见性。

在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(){})

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值