zoukankan      html  css  js  c++  java
  • 论JavaScript的作用域

         一直以来本人认为想深入了解一门语言,不光是让自己变成撸sir,更需要时间的锤炼。能经得起时间考验的东西更值得拥有。学习和使用Javascript一晃都7年了,最近才感觉自己对他才有顿悟,不知道是否来得有点迟。本文归纳了我对 JS中作用的理解,希望得学习有所帮助。

        特别说明:这是从另一个侧面(函数域的覆盖范围)来解释和说明执行上下文。

    一、作用域的理论理解

         从入门Javascript时,无论是学校老师,还是你工作的老司机,都会很认真的考虑你,Js中有一个全局作用域,然后他包含很多的子域(如:由function、object创建作用域的),子域是可以很轻松的访问父级域中的任何对象。这种表述你是否感觉很是空洞,难以理解。今本人就用浩瀚无边的地域来举个粟子:

    通过上面这个Image,让我一步一步带你领略作用域的魅力。

    1. 首先,地球:我们大家都很熟悉,他包含着你,我,以及世界上所有的国家(这儿就不论宇宙,否则会Hold不住),这肯定就是Js中的全局作用域了。地球包含天空、空气,正如Js中全局作用包含包含Number、String、Function、Object、Boolean、Regex等对象。

    2. 再者:中国、美国、朝鲜是三个平等的子作用域,他们都有利用地球 这个全局作用域的权利,如发射卫星。但美国再看不懂朝鲜,也不可能到朝鲜去干什么事情的。如Js的子作用域中可以任意使用Number、String等对象,但是没办法直接调用一个作用域平级的对象的方法。

    3. 再次:你做为一个中国公民,可以依法使用中国内部的资源(只不过要么交钱买,要么就是拿了税的),如果你想买点美国的的东西,那就需要new一个什么宝、或者什么东的来做中国与美国之间的引用,然后您懂的。如Js中需要访问一个平级作用域的内容时,那你就需要拿到被访问的引用。

    4. 最后:bind,apply,call,可以这样理解,bind就是在正规海购实体商场东西(预先可以看到实体的物品),而apply和call则是代购(只能视频看)。bind改变一个作用但此函数不会立刻执行,而apply和call则会立刻执行。

    二、示例代码说明作用域

    function Card(){
                this.name = 'name';
            }
            Card.prototype.getName =function(callback){
                callback();
                return this.name;
            }
    
            function PostCard(card){
                this.name = "postCard"
                this.card =card;
            }
            PostCard.prototype.getName =function(){
                var _name = this.card.getName(function(){
                    console.log("callback: " + this.name);
                });
                console.log(_name + "  " + this.name);
            }
    
            var card = new Card();
            var postCard = new PostCard(card);
            postCard.getName();

    1. 上述代码Card和PostCard就像第一部分提及的中国、美国一样,他们都有一个共同的父级作用域,就是window(地球)

    2. Card和PostCard是平级作用域,如PostCard的getName方法想访问Card的getName方法,就需要拿到Card的引用,如PostCard构造函数传入的card实例就是为了完成这个事情。

    3. Card的getName接受一个callback的高阶函数(这又是另外一个话题,函数式编程了),这里只要记住传入就是一个类型为function的形参就行了。然后在Card的getName方法中执行了callback,但这里你要注意,执行callback时没有通过任何方式或手段来指定他的作用域,所以callback执行作用域为window(地球)。

    4.输出结果:

    callback:
    name    postname

    三、示例代码说明bindapplycall

    function Direction(){
                this.direction = "mid";
            }
            Direction.prototype.set =function(val){
                this.direction = val;
            }
    
            var direction = new Direction();
            var dir02 = new Direction();
            direction.set.call(direction, "right");
            direction.set.apply(dir02, ["bottom"]);
    
            console.log(direction.direction);
            console.log(dir02.direction);
    
            //bind
            var tmp = direction.set.bind(dir02);
            tmp("bind after");
            console.log('..........................');
            console.log(direction.direction);
            console.log(dir02.direction);

    本示例代码提供了一个Direction函数,然后对this(当前实例)绑定了direction属性,且在Direction原型上绑定了set方法(用于修改this上的direction).

    1. 通过 new 创建了Direction的两个实例direction,dir02

    2. 通过call和apply改变作用域的指向,进行set方法的执行,call指向了direction实例,而apply指向了dir02的实例。这也展示了call与apply的区别,就是参数传送用一个列表,一个是数组。

    3. 通过输出结果大家会发现,虽然都是调用direction实例的set方法,但改变的this.direction却是对应的实例属性。

    4. 通过bind方法把direction实例的set方法与dir02相绑定,然后执行这个绑定,会发现改变是仍然是dir02实例的direction属性。

    5. 输出结果

    right
    
    bottom
    scope
    ..........................
    right
    bind after

    四、作用域的总结

    1. 只有一个全局作用域,但有无数个子作用域。

    2. 作用域的创建与执行:

       2.1 创建阶段[函数被调用,但内部代码还没开始执行]

       2.2 创建 作用域链

       2.3 创建变量  函数 以及参数

       2.4 决定this的值(也就是作用域,或者是执行上下文)

       2.5 代码执行[赋值、寻找函数引用以及解释/执行代码]

  • 相关阅读:
    oracle 物化视图导入导出报错
    算法导论------------桶排序算法之研究
    实现一个做双向NAT的虚拟网卡
    合理的keyword密度散布与黑帽SEO之躲藏文本
    Java发送Email
    ubuntu系统下设置静态IP
    Design Pattern Iterator 迭代器设计模式
    概率论高速学习03:概率公理补充
    鄂尔多斯
    衬衫面料品牌:Alumo_衬衫_男装_男装:衬衫、法式衬衫、袖扣领带、西服西裤等男士正装服饰-仕族官网
  • 原文地址:https://www.cnblogs.com/cqhaibin/p/7470597.html
Copyright © 2011-2022 走看看