闭包,原型链

闭包

在【函数定义】的时候,【函数对象】的【scope属性】便会引用包含该函数的上一级函数在运行时所生成的【执行上下文】的【活动对象】,由于发生对象属性之间的相互依赖,致使包含此函数的【scope属性】所指向的活动变量,在上一级函数【执行完毕】将要【释放执行上下文】的时候【不能释放】其包含的【活动变量】。浏览器

本身的理解: 闭包的产生首先要有一个地址被引用所指向闭包

函数与对象的关系

  1. 函数就是对象的一种
  2. 对象是函数建立的

prototype原型

  1. prototype是函数的一个属性
  2. 每个构造函数都有prototype属性
  3. prototype的值其实是一个对象
    • 这个对象默认只有一个constructor的属性,而且指向函数自己

构造函数中的属性和原型中的属性的区别

  1. 把属性定义在原型中比定义在构造函数中消耗的内存更小,由于在内存中一个类的原型只有一个,写在原型中的行为能够 被全部实例共享。实例化的时候并不会在内存中再复制一份。没有特殊缘由,通常把属性写到类中,行为写到原型中。
  2. 使用原型的方式定义属性,实际上不一样对象中的属性是共享的,也就是说对其中的任何一个对象修改了属性,其余对象的属性也会跟着发生变化,由于它们指向的是同一个地址,共享同一个属性
  3. 构造函数中定义的属性和方法比原型中定义的属性和方法优先级高。若是定义了同名称的属性和方法,构造函数中会覆盖原型中的。

隐式原型(对象)

隐式原型:_proto_是对象中的一个属性,每一个对象都有一个_proto_属性,也称为隐式原型。而且指向建立该对象的prototype
  1. 自定义函数本质上都是经过Object函数来建立的,因此它的_proto_指向Object.prototype
  2. Object.prototype的_proto_指向null

原型链

原型链:若访问对象属性时,先在基本属性中找,若是自身没有该属性,便会沿着_proto_这条链往上找。

执行上下文

在一段js代码执行前,浏览器已经作了一些准备工做,其中包括对变量的声明,变量赋值是在赋值语句执行的时候进行的。app

准备工做有三步:

  1. 变量:变量的声明,默认赋值为undefined
  2. this:赋值
  3. 函数声明:赋值

这三种数据的准备状况称之为“执行上下文”或者“执行上下文环境”;

函数每被调用一次,都会产生一个新的执行上下文环境,由于不一样的调用可能会有不一样的参数。
函数定义的时候就应经肯定了函数体内部变量的做用域

执行上下文栈

执行全局代码时,会产生一个全局上下文环境,每次调用函数,又会产生函数上下文环境,当函数调用完成时,这个上下文环境及其中的数据都会被销毁。再从新回到全局上下文环境。函数

处于活动状态的执行上下文环境只有一个。(压栈和出栈的过程)this

做用域和执行上下文

除全局做用域以外,每一个函数都会建立本身做用域。做用域在函数定义时就已经肯定了,而不是在调用时肯定。 做用域只是一个“地盘”,一个抽象的概念,其中没有变量,要经过做用域对应的执行上下文来获取变量的值,同一做用域下,不一样的调用会产生不一样的执行上下文环境,继而产生不一样的值。prototype

自由变量

在一个做用域中使用的变量,没有在其中声明(即在其余做用域中声明的),此时,这个变量对这个做用域来说就是自由变量(也可称为活动变量)code

做用域链

  1. 先在当前做用域查找X,若是有则获取并结束,若是没有则继续;
  2. 若是当前做用域是全局做用域,则证实X未定义,结束;不然继续;
  3. 将建立该函数的做用域做为当前做用域;
  4. 跳转到第一步。

继承

  1. 对象冒充对象

    function Person(name, age) {
               this.name = name;
               this.age = age;
               this.sayName = function() {
                   console.log(this.name);
               };
           }
    
           function Student(name, age) {
               this.obj = Person;
               this.obj(name, age);
               delete this.obj;
               this.study = function() {
                   console.log("study");
               }
           }
    
           var stu1 = new Student("zhangsan", 21);
           console.log(stu1.name, stu1.age);
           stu1.sayName();
           stu1.study();
  2. 原型链的方式继承

    function Person(name, age) {
       this.name = name;
       this.age = age;
       this.sayName = function () {
           console.log(this.name);
       };
    }
    function Student(name, age) {
       this.constructor(name, age);
    }
    Student.prototype = new Person();
    
    var stu1 = new Student("zhangsan", 21);
    console.log(stu1.name, stu1.age);
  3. call和apply方法内存

    function Student(name, age) {
    //            Person.call(this, name, age);
                Person.apply(this, [name, age]);
            }
    
            var stu = new Student("zhangsan", 21);
            console.log(stu.name, stu.age);
  4. 混合方式

    function Person(name, age) {
        this.name = name;
        this.age = age;
    }
    
    Person.prototype.sayName = function() {
        console.log(this.name);
    };
    
    function Student(name, age) {
        Person.call(this, name, age);
    }
    
    Student.prototype = new Person();
相关文章
相关标签/搜索