天天看點

js (this,原型與閉包)原型

this

  • 有對象指向對象;
  • 沒對象指向全局變量(window);
  • 有new指向new出的新對象;
  • bind,call&apply改變this的指向;
  • setTimeout/setInterval this指向window;
  • 箭頭函數 this 是由函數定義時候确定的

var adder = {

  base : 1,

  add : function(a) {

    var f = v => v + this.base;

    return f(a);

  },

  addThruCall: function inFun(a) {

    var f = v => v + this.base;

    var b = {

      base : 2

    };

    return f.call(b, a);

  }

};

console.log(adder.add(1));

var obj = {

  i: 10,

  b: () => console.log(this.i, this),

  c: function() {

    console.log( this.i, this)

  }

}

obj.b();  // undefined window{...}原型

obj.c();  // 10 Object {...}

原型

prototype:

  • prototype:每一個對象都會在其内部初始化一個屬性:即prototype;
  • 原型鍊:當我們通路一個對象的屬性時,如果這個對象内部不存在這個屬性,那麼就回去__proto__裡找這個屬性,這樣一直找下去就是:原型鍊;
  • instanceof 原理是判斷執行個體對象的__proto__和生成該執行個體的構造函數的prototype是不是引用的同一個位址。
  • hasOwnProperty

     是 JavaScript 中唯一一個處理屬性但是不查找原型鍊的函數。
js (this,原型與閉包)原型

構造函數  ->prototype-> 原型對象 -> constructor -> 構造函數

構造函數 -> new -> 執行個體對象

執行個體對象 -> __proto__-> 原型對象-> __proto__->原型對象->->null

執行上下文:

變量聲明與函數聲明,其作用域會提升到方法體的頂部;

作用域:

  • javascript沒有塊級作用域
  • javascript除了全局作用域之外,隻有函數可以建立的作用域。作用域在函數定義時就已經确定了。而不是在函數調用時确定。

閉包:

  • 概念: 内部函數可以通路外部函數中的變量;
  • 使用:函數作為傳回值;函數作為參數;
  • 作用:封裝變量,收斂權限;
  • 缺點:消耗記憶體

建立對象的方法:

  • 對象字面量;
  • 構造函數;
  • 立即執行函數;
  • Object.create();

new 對象過程:

  • 建立新對象;
  • this指向這個新對象;
  • 執行代碼;
  • 傳回this;

類與繼承:

類的聲明:

function Animal(){
    this.name = 'name';
}

// es6 

class Animal2{
    constructor(){
        this.name = 'name2';
    }
}
           

繼承:

1.借助構造函數實作繼承

function Parent(){
    this.name = 'parent';
}

function Child(){
    Parent.call(this);
    this.type = 'child1';
}
           

缺點:部分繼承;繼承不到父類原型對象上的方法;(隻有父類的屬性挂載到子類上了,Child的prototype沒變為Child.prototype繼承不了Parent的prototype)

2.原型鍊繼

function Parent(){
    this.name = 'name';
}
function Child(){
    this.type = 'child';
}

Child.prototype = new Parent();
           

缺點:原型鍊上原型對象是共用的。(原型的屬性修改,所有繼承自該原型的類的屬性都會一起改變)

3.組合方式

function Parent(){
    this.name = 'parent';
}
function Child(){
    Parent.call(this);
    this.type = 'child';
}
Child.prototype = new Parent();
           

缺點:父類執行函數執行兩次;constructor指向父類;

function Parent(){
    this.name = 'parent';
}
function Child(){
    Parent.call(this);
    this.type = 'child';
}
Child.prototype = Parent.prototype;
           

缺點:子類constructor指向父類

function Parent(){
    this.name = 'parent';
}
function Child(){
    Parent.call(this);
    this.type = 'child';
}
Child.prototype = Object.create(Parent.prototype);
Child.prototype.constructor = Child;
           

優點:子類的原型指向Object.create(Parent.prototype),實作了子類和父類構造函數的分離,但是這時子類中還是沒有自己的構造函數,是以緊接着又設定了子類的構造函數,由此實作了完美的組合繼承。(也就是把父類的prototype寫入子類的prototype,在定義子類的constructor)

4. es6

class Child extends Parent {
    constructor(){

    }
}
           
js