1、ECMAScript中有两种属性:

  数据属性和访问器属性;

  数据属性(4个特性用于描述):

    configurable:

      能否通过delete删除属性而重新定义属性;

      能否修改属性的特性;

      能否把属性修改为访问器属性。

    enumerable:

      能否通过for-in循环返回属性。

    writable:

      能否修改属性的值。

    value:

      包含这个属性的数据值。

    特点:

      直接在对象上的属性(字面量形式或new Object()形式),默认值分别为:

        configurable:true

        enumerable:true

        writable:true

        value:undefined。

      调用Object.defineProperty()方法创建一个新的属性时:

        如果不指定(意味着可以指定),configurable、enumerable、writable的默认值均为false;

        如果是修改已定义的属性的特性,则无此限制。

      重点理解configurable:false:

        可能是把configurable设置为false,也可能是调用...创建...新...属性时忘记设置configurable;

        此时再调用Object.defineProperty()方法去修改除writable之外的特性,会导致错误:

          注意是去修改,如果调用了方法,为某个特性重新设置一样的值,这是不会报错的

          "除writable之外"没有得到验证?

  访问器属性(4个特性):

    get、set和 . = 的关系?

2、Uncaught RangeError: Maximum call stack size exceeded:栈溢出?

  Object.defineProperty(o,"x",{
    get:function(){  //?
      return this.x;
    },
    set:function(arg){
      this.x = arg;
      this.y = arg + x;
    }
   });

3、对象通俗理解就是一组名值对,其中值可以是数据或函数。

4、自定义对象的toString()需要自己重写override。

5、创建对象:

  工厂模式没有解决对象识别的问题;

  构造函数模式:

    将构造函数的作用域赋给新对象,因此this就指向了这个新对象:

      函数的作用域和函数的this属性是什么关系?this大概与函数执行环境有关

      函数如果有调用者,则this就指向调用者;

      可以使用函数的call/apply方法为this指定指向对象;

      对象也有作用域的概念;

      当在全局作用域中调用一个函数时,this对象总是指向Global对象(浏览器中的window对象)。

    构造函数的每个不同实例都有一个constructor属性,指向构造函数自己,原生函数同样;

    区别构造函数与普通函数就是是否使用了new操作符调用:

      如果不使用new来调用构造函数,属性和方法都被添加给window对象。

    构造函数的问题是不同实例的同名函数是不相等的。

  原型模式:

    每个函数都有一个prototype(原型)属性,指向 通过调用构造函数创建的那个实例的 原型对象;

    原型对象包含可以由特定类型的所有实例共享的属性和方法;

    3个问题:

      1.所有实例共享属性和方法?

        共享方法就是函数在堆内存中的地址被赋给栈空间中的不同变量;

        共享属性该如何理解?

      2.封装问题?:

        构造函数代码与prototype部分代码形式上有些分散。

      3.对象的初始化问题?:

        没有字面量的优势。

      4.原型对象与构造函数是一一对应的吗?

    构造函数的原型对象 实例的原型对象 本质上是同一个对象;

    原型模式中,实例与构造函数没有直接的关系:

      但是构造函数模式中,构造函数的每个不同实例都有一个constructor属性,指向构造函数,这在原型模式中也得到了验证?否:

      

    总结:

      1.构造函数有prototype属性,指向构造函数的原型对象;

      2.原型对象有constructor属性,指向对应的构造函数;

      3.函数的每个实例有[[Prototype]]属性(或_proto_),指向实例的原型对象;

      4.实例的原型对象和函数的原型对象是同一个对象;

      5.访问原型对象有两种方式:

        a.通过构造函数:Person.prototype

        b.通过函数实例:Object.getPrototypeOf(person)

      6.规则不局限于构造函数,只要是创建一个函数;

      7.当为对象添加一个属性时,这个属性就会屏蔽原型对象中保存的同名属性

    in操作符作用于对象,当然也包括原型对象:
      for/in枚举返回的属性均是String基本类型。

    constructor属性的[[Enumerable]]特性默认是false,即是不可枚举的;

    重写原型对象:

      会切断构造函数与最初原型之间的双向链接关系;

      已创建的实例不会直接链接到新的原型对象,实际上是通过最初原型与构造函数间接链接到新原型对象:

        Object.getPrototypeOf(p8).constructor.prototype.name。

      注意:当创建一个函数(显示定义)时,原型对象就会生成,而非使用new调用构造器时才生成。

6、变量名:

  变量名是给编译器看的,编译器根据变量是局部还是全局分配内存地址或栈空间;

  变量名在内存中不存在,操作时转换成地址数存放在寄存器中:

    编译器会将合法的变量名放到一个叫“符号表”的一个表中,每个符号对应一个地址;
    当你调用此变量时,就会根据此符号表找到对应的地址,然后进行操作。

  定义int a;时,编译器分配4个字节内存,并命名该4个字节的空间名字为a(即变量名):
    当用到变量名a时,就是在使用那4个字节的内存空间。
  5是一个常数,在程序编译时存放在代码的常量区存放着它的值(就是5):
    当执行a=5时,程序将5这个常量拷贝到a所在的4个字节空间中,就完成了赋值操作。
7、操作符的顺序问题:
  application.getComps() + application instanceof Op:这种情况下是从左往右执行,说明+和instanceof属于同级操作符?
8、原型链的第二个问题如何理解?
9、原型链是实现继承的一种方式。
10、组合的含义:
  组合使用构造函数模式和原型模式、组合继承;
  组合就是对 共享的原型属性和方法 实例属性 分开处理。
11、函数设置为null?:
  函数对象占用的堆空间被释放了吗?
    如果此时该空间还被其它函数名引用,就不会被释放;
    如果没有,是等待垃圾回收机制处理。
12、关于作用域链:
  1.每个函数在创建时都会拥有属于自己作用域链:
    作用域链被保存在函数内部的[[Scope]]属性,独立于其它函数;
    作用域链的构建过程:
      最先添加包含该函数的活动对象,然后逐级往外,直到添加全局变量对象;
      注意此时不会添加该函数自己的活动对象。
  2.每个函数在执行时都会创建自己的执行环境和活动对象:
    通过复制[[Scope]]属性中的对象构建起执行环境的作用域链;
    然后将活动对象其添加到作用域链的前端;
    注意:
      函数的活动对象 就是 函数的执行环境的变量对象;
      变量对象可以被其它函数的作用域链跨级共享,方便标识符搜索。
  3.每个函数执行完毕后:
    执行环境会被立即销毁;
    作用域链不会被销毁?,方便下次调用:
      作用域链是在创建函数时被创建的,而函数只会在编译时被创建?有异议。
         但销毁活动对象应满足:
      该活动对象在当前所有活动对象的最前面。
13、闭包是指有权访问另一个函数作用域中的变量的函数
  如在访问某函数的私有变量时:
    函数的私有变量(包括参数、局部变量(var修饰)、内部自声明定义的函数),外界不能直接访问;
    可以使用闭包:
      由于闭包会将外部函数的活动对象添加到自己的作用域链,那么就可以在闭包中访问外部函数中的任何私有变量;
      但是闭包也会导致内存泄漏问题:
        只要闭包未执行完毕,闭包的作用域链就不会释放外部函数的活动对象。
14、匿名函数的执行环境具有全局性?this对象通常指向window。