zoukankan      html  css  js  c++  java
  • js深入(一)从原型理解原型链

    ## 构造函数创建一个对象
    function Person() {
    
    }
    var person = new Person();
    person.name = 'zhangsan';
    console.log(person.name) // zhangsan
    

    上边这个例子,我们通过构造函数创建了一个实例,从这个实例到他的原型到最后得object,他们之间得关系,就形成了一个原型链

    prototype proto 和 constructor

    首先上边这个例子里边,我们声明了一个构造函数,在后再这个构造函数里边有一个prototype的属性。

    注意这个prototype属性,是只有函数才会有属性

    Person.prototype.name = 'zhangsan';
    var person1 = new Person();
    var person2 = new Person();
    console.log(person1.name) // zhangsan
    console.log(person2.name) // zhangsan
    

    首先我们看到再函数的prototype属性上边我们定义了一个name属性,然后通过new创建了两个实例,
    然后通过调用实例的name属性,也可以拿到构造函数prototype属性上边的name属性,
    那么这个prototype到底是有什么用处呢,

    • prototype

    这个只有函数才会有的属性,他其实指向了一个对象,而这个对象就是调用了构造函数创建实例的原型
    ,可以理解成是person1,person2在创建的时候从他们的原型把原型的属性委托给了person1和person2

    这里为什么不叫他继承,因为继承的定义是赋值一个一模一样的实例出来,但是js里边并不会复制

    • proto

    这个__proto__属性是每个对象实例都会有的一个属性,这个属性也会指向该对象的原型

    function Person() {}
    var person1 = new Person();
    console.log(person1.__proto__ === Person.prototype); // true
    

    可以粘贴一下代码到浏览器打印一下person1 可以看到__proto__这个属性

    • constructor

    constructor这个属性之前我也叫他构造函数,叫习惯了,因为每个原型上边都会有一个constructor这个属性,指向其相关的构造函数

    function Person() {}
    console.log(Person === Person.prototype.constructor); // true
    

    原型链的查找机制

    首先在你创建一个实例的时候,你去读取实例上边的属性,他会首先再实例上边去查找,如果找不到,那么就去这个实例的原型上边去找,如果还是找不到,就会去原型的原型上边去找,直到最后找到Object对象,当然object对象也是有原型的 就是null

    记得之前的时候,遇到过这么一个问题就是typeof null的 时候为什么是个object,记得当时得到的答案是说null是一个对象的空指针,从现在来看null打印object是有原因的

    那么还是查找不到的话会怎么样的,不要慌(.゚ー゚), 他会返给你一个undefined(.゚ー゚)

    最后拉一张图

    图中蓝色的这个链状的结构的线就是原型链

    js的作用域

    首先什么叫做作用域

    作用域是指程序源代码中定义变量的区域。

    作用域规定了如何查找变量,也就是确定当前执行代码对变量的访问权限。

    JavaScript 采用词法作用域(lexical scoping),也就是静态作用域。

    var value = 1;
    
    function foo() {
        console.log(value);
    }
    
    function bar() {
        var value = 2;
        foo();
    }
    
    bar();
    

    网上拿来的例子,直接说过程

    在执行阶段执行foo的时候,直接在foo寻找value ,因为js是静态作用域,所以在foo里边没有找到的时候,直接去上一层找,最后结果是1

    var value = 1;
    
    
    function bar() {
        var value = 2;
        console.log(value);
    }
    
    bar();
    

    同理这段代码bar里边有value 直接打印2

    那么再看一个例子

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

    这个例子会打印出什么,大家可以猜一猜

    结果就是local scope

    那么为什么上边的第一段代码里边同样是在函数里边执行另一个函数,但是他不会用第一个函数里边的变量呢,

    原因就是js是静态作用域,js执行一个函数的时候分为两个阶段,首先会解析一变,这个时候确定了词法作用域和this指向,属性声明等,然后才是函数执行阶段

    函数的作用域是基于函数创建的位置的,所以第一段代码和下边这段代码的函数作用域是不想同的

    说到这里的时候,我在上文中提到了执行上下文和函数执行的过程,之前在我得另一篇博客里边写道过,有兴趣的可以去看下 js的堆栈队列

    以上是我对js原型链和作用域的一些认识,有不足的希望指正

  • 相关阅读:
    PAT (Advanced Level) 1080. Graduate Admission (30)
    PAT (Advanced Level) 1079. Total Sales of Supply Chain (25)
    PAT (Advanced Level) 1078. Hashing (25)
    PAT (Advanced Level) 1077. Kuchiguse (20)
    PAT (Advanced Level) 1076. Forwards on Weibo (30)
    PAT (Advanced Level) 1075. PAT Judge (25)
    PAT (Advanced Level) 1074. Reversing Linked List (25)
    PAT (Advanced Level) 1073. Scientific Notation (20)
    PAT (Advanced Level) 1072. Gas Station (30)
    PAT (Advanced Level) 1071. Speech Patterns (25)
  • 原文地址:https://www.cnblogs.com/netUserAdd/p/11111021.html
Copyright © 2011-2022 走看看