function

// new 的實現原理 // 簡單的雙向綁定 1.new 2.Function 3.this 若是函數掛載在一個對象上,做爲對象的一個屬性,就稱它爲對象的方法。當經過這個對象來調用函數時,該對象就是這次調用的上下文(context),也就是該函數的this的值。 4.constructor 用於初始化一個新建立的對象的函數就是這次調用的上下文。 在JS中函數即對象,程序能夠隨意操控它們。好比:JS能夠把函數賦值給變量,或者做爲參數傳遞給其餘函數。由於函數就是對象,因此能夠給它們設置屬性,甚至調用它們的方法。 JS的函數可嵌套在其餘函數中定義,這樣它們就能夠訪問它們被定義時所處的做用域中的任何變量。這意味着JS函數構成了一個閉包(closure),它給JS帶來了很是強勁的編程能力。編程

嵌套函數bash

function hypotenuse(a, b) {
    function square(x) {
        return x * x
    }
    return Math.sqrt(square(a) + square(b))
}

function square(x) {return x * x}
function hypotenuse(a, b) {
    return Math.sqrt(square(a) + square(b))
}
複製代碼

函數調用 構成函數主體的JS代碼在執行之時並不會調用,只有調用該函數時,它們再回執行。有4種方式來調用JS函數。閉包

1.做爲函數調用,對於普通的函數調用,函數的返回值成爲調用表達式的值。若是該函數返回值是由於解釋器到達結尾,返回值就是undefined。若是函數返回是由於解釋器執行到一條return語句,返回值就是return以後的表達式的值,若是return語句沒有值,則返回undefined。app

2.做爲方法調用,方法和this關鍵字是面向對象編程範例的核心。任何函數只要做爲方法調用實際上都會傳入一個隱式的實參------這個實參是一個對象,方法調用的母體就是這個對象。函數

var o = {
    m: function () {
        var self = this
        console.log(this === o)
        f()
        function f() {
            console.log(this === o)
            console.log(self === o)
        }
    }
}
o.m()
複製代碼

3.做爲構造函數ui

若是函數或者方法調用以前帶有關鍵字new,它就構成構造函數調用。構造函數調用和普通的函數調用以及方法調用在實參處理、調用上下文和返回值方面都有不一樣。 構造函數調用建立一個新的空對象,這個對象繼承自構造函數的prototype屬性。構造函數試圖初始化這個新建立的對象,並將這個對象用作其調用上下文,所以構造函數能夠使用this關鍵字來引用這個新建立的對象。this

4.經過它們的call()和apply()方法間接調用spa

JS中函數也是對象,函數也能夠包含方法。 函數能夠被任意次執行或調用。prototype

原型鏈 1.建立對象有幾種方法 2.原型、構造函數、實例、原型鏈 3.instanceof的原理 4.new運算符雙向綁定

1.建立對象有幾種方法

方法1
var a = {name: 'mary'}
var b = new Object({name: 'john'})
a、b結果相同

方法2
var M = function(name) {this.name = name}
var c = new M('henri')

方法3
var P = {name: 'john'}
var d = Object.create(P)
d.__proto__ === p // true
複製代碼

每個JS對象都和另外一個對象相關聯,每個對象都從原型繼承屬性。

2.原型、構造函數、實例、原型鏈

實例:a,b,c都稱爲實例 構造函數:構造函數也是函數,任何函數只要被new操做的函數,就是構造函數。不使用new就是普通的函數。 函數:函數都有一個prototype屬性,聲明函數的時候就會被js引擎帶上。對象沒有prototype。實例有__proto__,函數沒有。 原型對象:經過constructor(構造器)來區分被哪一個構造函數所引用。

M.prototype.constructor === M

c.__proto__ === M.prototype

M.__proto__ === Function.prototype

M.prototype.__proto__ === Object.prototype  // true
Object.prototype是整個原型鏈的頂端

M.prototype.run = function () {
    console.log('run fast')
}
var e = new M('mary')
此時c、e都有了run方法
複製代碼
  1. instanceof 原理 instanceof判斷對象的類型 判斷實例對象的__proto__和構造函數的prototype是否爲同一個引用(同一個地址),整條原型鏈上的都會返回true
c instanceof M // true
c instanceof Object // true
c.__proto__ === M.prototype // true
M.prototype.__proto === Object.prototype // true
c.__proto__.constructor === M // true
c.__proto__.constructor === Object // false
所以用constructor比用instanceof更嚴謹
複製代碼
  1. new運算符

4.1 一個新對象被建立。它繼承自foo.prototype 4.2 構造函數foo被執行。執行的時候,相應的傳參會被傳入,同時上下文(this)會被指定爲這個新實例。new foo等同於new foo(),只能用在不傳遞任何參數的狀況下 4.3 若是構造函數返回了一個「對象」,那麼這個對象會取代整個new出來的結果。若是構造函數沒有返回對象,那麼new出來的結果爲步驟1建立的對象

new運算符背後的原理
var f = function(func) {
    var o = Object.create(func.prototype)
    var k = func.call(o)
    if (typeof k === 'object') {
        return k
    } else {
        return o
    }
}

var h = f(M)
h instanceof M
h instanceof Object
h.__proto__.constructor === M
複製代碼

函數其實是對象,每一個函數都是Function類型的實例,並且與其餘引用類型同樣具備屬性和方法。因爲函數就是對象,所以函數名實際上也是一個指向函數對象的指針,不會與某個函數綁定。M.proto === Function.prototype function M () {

} M.proto === Function.prototype

用constructor判斷比instanceof要準確

__proto__

  • 對象特有
  • 指向上層(建立本身的那個構造函數)的prototype
  • 所以對象能夠從prototype中繼承屬性和方法

prototype

  • 函數特有
  • 用於存儲要共享的屬性和方法

constructor

  • 函數特有,定義在prototype裏面
  • 經過new建立實例時,該實例變繼承了prototype的屬性和方法

Object:既是對象,也是構造函數

  • 做爲對象: Object.__proto__ === Function.prototype
  • 做爲函數: Object.prototype是原型鏈的頂端,Object.prototype.__proto = null

Function: 既是對象,也是構造函數

  • 做爲對象:Function.__proto__ === Function.prototype
  • 做爲函數:Function.prototype用於共享,而Function.prototype.__proto__繼承自Object.prototype

Array(Date、Number...):既是對象,也是構造函數

  • 做爲對象:Array.__proto__ === Function.prototype
  • 做爲函數:Array.prototype用於共享,Array.prototype.__proto__繼承自Object.prototype

對象Person: 既是對象,也是構造函數

  • 做爲對象:Person.__proto__ === Function.prototype
  • 做爲函數:Person.prototype用於共享,·Person.prototype.__proto繼承自Object.prototype

所以: 一、原型鏈頂端是Object.prototype 二、構造函數建立的對象(Object、Fucntion、Array、普通對象等)都是Function的實例,它們的__proto__均指向Function.prototype 三、除了Object,全部對象(或構造函數)的prototype,均繼承自Object.prototype

相關文章
相關標籤/搜索