javascript面向对象详解--作用域链

in JavaScript with 0 comment

先来看一下js面向对象的写法演进

//面向对象 一
  /*  
    function makePerson(first, last) {
      return {
        first: first,
        last: last
      }
    }

    function personFullName(person) {
      return person.first + ' ' + person.last
    }

    function personFullNameReversed(person) {
      return person.last + ', ' + person.first
    }
    var s = makePerson('Simon', 'Willision')
    console.log(personFullName(s))
    console.log(personFullNameReversed(s))
*/

 //面向对象 二
 /*
     function makePerson(first, last) {
       return {
         first: first,
         last: last,
         fullName: function() {
           //this表示调用了当前函数的对象,即谁调用,对象就是谁
           console.log(this)
           console.log(this.first)
           return this.first + ' ' + this.last
         },
         fullNameReversed: function(){
           return this.last + ', ' + this.first
         }
       }
     }
     var s = makePerson('Simon', 'Willision')
     var fc = s.fullName
     fc()
    //console.log(s.fullName())
    //console.log(s.fullNameReversed())
*/

  // 面向对象 三
  /*
     function Person(first, last) {
       this.first = first
       this.last = last
       this.fullName = function() {
         console.log(this)
         return this.first + this.last
       }
       this.fullNameReversed = function() {
         return this.last + ' ,' + this.first
       }
     }
     //每次创建对象都会创建两个函数,不好,并且里边还形成了闭包,影响性能
     var s = new Person('Simon', 'Willision')
     //var fn = s.fullName
     //console.log(fn())
     console.log(s.fullName())
     */

  //面向对象 四, 函数定义太分散不好
  /*
    function personFullName(){
      return this.first + ' ' + this.last
    }
    function personFullNameReversed() {
      return this.last +', ' + this.first
    }
    function Person(first, last) {
      this.first = first
      this.last = last
      this.fullName = personFullName
      this.personFullNameReversed = personFullNameReversed
    }
    */
    //面向对象 五,使用原型, 终极方案
    
    function Person(first, last) {
      this.first = first
      this.last = last
    }
    Person.prototype.fullName = function() {
      return this.first + ' ' + this.last
    }
    Person.prototype.fullNameReversed = function() {
      return this.last + ', ' + this.first
    }
    const myPerson = new Person('jack','fa')
    console.log(myPerson)
   //原型这个特性功能十分强大,JavaScript 允许你在程序中的任何时候修改原型(prototype)中的一些东西,
   //也就是说你可以在运行时(runtime)给已存在的对象添加额外的方法,因此javascript是动态语言,这是非常灵活的

js作用域链

如果一个变量在当前作用域下找不到,那就找"父级"作用域,如果父级也没呢?再一层一层向上寻找,直到找到全局作用域还是没找到,就宣布放弃。这种一层一层的关系,就是 作用域链 。

注意:刚才的"父级"打引号了,其实这种说法不严谨,其实寻找变量是要到创建这个函数的那个域去找,在创建它的作用域中取值,这里强调的是"创建",而不是"调用"

js作域在ES6之前只有全局和函数级作用域,没有块级作用域

作用域与执行上下文(scope and context)

JavaScript 属于解释型语言,JavaScript 的执行分为:解释和执行两个阶段,这两个阶段所做的事并不一样:

解释阶段:

执行阶段:

JavaScript 解释阶段便会确定作用域规则,因此作用域在函数定义时就已经确定了,而不是在函数调用时确定,但是执行上下文是函数执行之前创建的。执行上下文最明显的就是 this 的指向是执行时确定的。而作用域访问的变量是编写代码的结构确定的。

执行上下文(context)在运行时确定,随时可能改变;作用域(scope)在定义时就确定,并且不会改变。

一个作用域下可能包含若干个上下文环境。有可能从来没有过上下文环境(函数从来就没有被调用过);有可能有过,现在函数被调用完毕后,上下文环境被销毁了;有可能同时存在一个或多个(闭包)。同一个作用域下,不同的调用(比如使用call/apply/bind)会产生不同的执行上下文环境,继而产生不同的变量的值。

评论已关闭.