JS高级03_对象的创建、继承、GC

1. 对象的创建(设计)模式

1). Object构造函数模式

缺点:语句多,流程繁杂

var obj = {}
obj.name = 'Tom'
obj.setName = function(name){this.name=name}

2). 对象字面量模式 {}一下都定义了

优点:书写简单,直观。

缺点:new多个实例对象的时候,重复代码多。

var obj = {
    name : 'Tom',
    setName : function(name){this.name = name}
}

3). 构造函数模式

优点:可以大量new,避免重复代码

缺点:不能明确区分属于哪一类

function Person(name, age) {
    this.name = name
    this.age = age
    this.setName = function(name){this.name=name}
}
new Person('tom', 12)

4). 构造函数+原型的组合模式

方法写在原型上,可以不用每次new一个实例,都开辟出内存空间,比较省内存。

function Person(name, age) {
    this.name = name
    this.age = age
}
Person.prototype.setName = function(name){this.name=name}
new Person('tom', 12) 

2. 继承

1). 原型链继承 : 继承方法

  • 子类的原型对象===父类的实例,例如:child.prototype = new Parent();

  • 注意点:以上的步骤会导致子类原型的构造器属性丢失,所以需要手动添加构造器属性

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    child.prototype.constructor = child;

    function Parent(){}
    Parent.prototype.test = function(){}
    function Child(){}

    Child.prototype = new Parent() //△子类原型指向父类的实例
    Child.prototype.constructor = Child //△然后手动校正 子类的构造器属性重新指向子类(因为上面的操作会新指向一个内存,而丢弃原有的原型对象内存,原有的是有构造器属性的。)

    var child = new Child()
    child.test() //调用父类型的方法

2). 借用构造函数 : 得到属性,无继承关系

  • 在子类的构造函数中调用父类的构造函数-注意点:父类构造函数的this指向问题

  • 解决方案:通过call/apply强制修改this的指向 —> 当前子类的实例对象

    1
    2
    3
    4
    5
    6
    7
    function Parent(xxx){this.xxx = xxx}

    function Child(xxx,yyy){
    Parent.call(this, xxx) //△借用父类型的构造函数。不写this就window调用了,写半天也没把xxx属性写到子类上。
    //或Parent.apply(this,[xxx]) apply与call用法不同,得是数组。
    }
    var child = new Child('a', 'b') //child.xxx为'a', 但child没有test()

3). 组合

function Parent(xxx){this.xxx = xxx}
Parent.prototype.test = function(){}
function Child(xxx,yyy){
  Parent.call(this, xxx) //借用构造函数   this.Parent(xxx)
}
Child.prototype = new Parent() //得到test()
Child.prototype.constructor = Child
var child = new Child() //child.xxx为'a', 也有test()

3. 理解

1). 定义一个函数背后做了什么?

创建一个Function的实例对象
给对象添加prototype属性, 其值为object空对象(原型对象)
给原型对象添加constructor属性, 指向当前函数对象

2). new一个对象背后做了些什么?

创建一个新的空对象
给对象设置__proto__, 值为构造函数对象的prototype属性值
通过对象执行构造函数体(给对象添加属性/方法)

垃圾回收GC

garbage collection
垃圾回收机制:循环机制,反复检测环境中的垃圾

1.计数清除

IE低版本,老的chrome
看内存的地址身上有几个指针指向,当一块内存地址身上指针个数为0,说明这块内存马上要被回收

1
2
3
4
5
6
7
8
9
10
11
12
13
14
var obj = {name : ' kobe ' }
obj = null;

//但是以下互相指的情况不会被GC
var obj = {
a: obj1
}

var obj1 = {
b: obj
}

obj = null;
obj1 = null;

2.标记清除

进入到代码行的环境以后检测到 需要使用的变量 就在其身上加一个进场标记,在代码执行完将return的时候,就会在 之前加标记的变量的身上 再添加一个出场标记