浅析Js之 “作用域链与原型链“篇

2,118 阅读2分钟

一、作用域链

在谈及作用域链之前,首先要谈谈作用域

1.作用域(Scope)

概念:在某一区域执行Js代码时,需对变量或函数的值进行访问,而这一区域又提供对变量或函数的查找,并确定是否可以访问,则称该区域为作用域

作用域可分为全局作用域(Global)与局部作用域(Local)

代码示例:

<script>
var  a = 1;     //全局变量
function f(){
    var b = 2;  //局部变量
    console.log(a,b)    //1 2
}
f();
console.log(b)   //Uncaught ReferenceError:   b is not defined
</script>

Js中并没有块级作用域,都是相对函数而言的,而ES6新增可以在函数内用Let声明变量,使变量只能在代码块内有效

2.作用域链(Scope Chain)

概念: Js作用域链其实就是从函数内部访问外部函数外部变量的一种机制,它从内到外进行链式查找,那么他是如何进行查找的呢?以下从执行上下文的角度分析

代码示例:

<script>
var a = 1;
function f(){
    var b = 2;
    var c = 3;
    function f1(){
        var d = 4;
        function f2(){
            console.log(b,c,d);     //2,3,4
        }
        f2();
    }
    f1();
    console.log(b,c);   //2,3
    console.log(d);     //Uncaught ReferenceError: d is not defined
    }
f();
</script>

由于函数里面再次定义了函数,所以呢,形成一个执行上下文的前后相互引用的关系,也就产生一个作用域链。

二、原型链(Prototype Chain)

1. 原型(Prototype)

  • prototype其实就是原型,每一个函数都有一个原型,它的值是一个对象;
  • 在对象的实例化中包含了很多属性,但其中一定有一个Constructor方法,它指向函数本身
  • _proto_也是每一个对象都具有的属性,它指向创建这个对象的prototype

2. 原型链(Prototype Chain)

概念: 如果访问一个对象的属性时,先在这个对象自己的属性中去找,如果找不到,则沿着_proto_这个属性向中找,如果_proto_这个对象中还是没有找到,就在_proto_对象的_proto_属性中去找,依次下去,这就是原型链。

代码示例:

Function.prototype.new = "New Function !";
function f(){}
console.log(f.new);     //  New Function !

图示如下:

函数f调用new方法,先从自己的_proto_找,找不到就往Functionprototype中找,由于我在Function中创建了一个new方法,所以可以找到

由于对象的__proto__[隐式原型]与创建这个对象的函数(构造器)的prototype是一致的。 所以理论上,你对__proto__修改会直接影响prototype。

3. 原型扩展:继承

<script>
 function Parent(yourname){
        this.name = yourname;
    }
    
Parent.prototype.say = function (){
        console.log(this.name);
    }
    
function Son(yourname){
        Parent.call(this,yourname);     //调用父对象的构造器,把当前子类的对象传给this
    }
    
Son.prototype = Parent.prototype;       //让子对象的_proto_指向父对象的prototype
Son.prototype.constructor = Son;        //让prototype原型上的constructor在指向Son
var s = new Son('Alex');
s.say();                            //  Alex
</script>

结语:学疏才浅,仅供学习与交流