国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

Javascript函數執行、new機制以及繼承

sshe / 1253人閱讀

摘要:函數執行一個函數,被執行有三種途徑或機制以及繼承中定義了一種對象,稱之為對象,其內部實現包括以下說明該對象可以被執行,具有屬性說明該對象可以接受操作,具有構造器屬性指向對象的原型鏈。

JS函數執行

一個JavaScript函數fn,被執行有三種途徑:

fn()

new fn()

fn.call()或fn.apply()

new機制以及繼承

JavaScript中定義了一種對象,稱之為ECMAScript對象,其內部實現包括以下:

__call__: 說明該對象可以被執行,具有function屬性

__construct__: 說明該對象可以接受new操作,具有構造器屬性

__prototype__: 指向對象的原型鏈。對于定義的函數,會指向Function.prototype

注意:__prototype__是原型鏈,對所有對象都有的。prototype是原型,是函數才有的,就是一個普通的對象而已,目的是為了接受new后給生成的對象提供原型鏈的。

執行fn就是調用__call__

執行new fn()會進行以下簡化過程:

新建一個對象,記作o

把o.__prototype__指向fn.prototype(如果fn.prototype不是一個Object,則指向Object.prototype)

執行fn,并用o作為this(即內部實現的fn.call(this))。如果fn返回是一個object,則返回object, 否則把o返回

fn.call(obj)或者fn.apply(obj)就是將obj作為this,執行fn。本質是調用__call__,只是傳入了obj作為this.

    //定義一個函數,正常函數會具有__call__, __construct__
    //同時Parent.__proto__指向Function.prototype
    function Parent() {
        this.sayAge = function() {
            console.log("age is: " + this.age);
        }
    }
    //原型上添加一個方法
    Parent.prototype.sayParent = function(){
        console.log("this is Parent Method");
    }
    
    //定義另一個函數
    function Child(firstname){
    
        //這里就是調用Parent的__call__, 并且傳入this
        //而這里的this,是Child接受new時候生成的對象
        //因此,這一步會給生成的Child生成的實例添加一個sayAge屬性
        Parent.call(this);
        
        this.fname = firstname;
        this.age = 40;
        this.saySomething = function() {
            console.log(this.fname);
            this.sayAge();
        }
    }
    
    //這一步就是new的調用,按原理分步來看
    //1. 新建了個對象,記作o
    //2. o.__prototype__ = Parent.prototype, 因此o.sayParent會訪問到o.__prototype__.sayParent(原型鏈查找機制)
    //3. Parent.call(o), 因此o也會有個sayAge屬性(o.sayAge)
    //4. Child.prototype = o, 因此 Child.prototype 通過o.__prototype__ 這個原型鏈具有了o.sayParent屬性,同時通過o.sayAge 具有了sayAge屬性(也就是說Child.prototype上具有sayAge屬性,但沒有sayParent屬性,但是通過原型鏈,也可以訪問到sayParent屬性)
    Child.prototype = new Parent();
    
    //這也是一步new調用
    //1. 新建對象,記作s
    //2. s.__prototype__ = Child.prototype, 此時s會具有sayAge屬性以及sayParent這個原型鏈上的屬性
    //3. Child.call(s), 執行后, 增加了fname, age, saySomething屬性, 同時由于跑了Parent.call(s), s還具有sayAge屬性, 這個屬性是s身上的, 上面那個sayAge是Child.prototype上的, 即s.__prototype__上的。
    //4. child = s
    var child = new Child("張")
    
    //child本身屬性就有,執行
    child.saySomething();
    
    //child本身屬性沒有, 去原型鏈上看, child.__prototype__ = s.__prototype__ = Child.prototype = o, 這里沒找到sayParent, 繼續往上找, o.__prototype__ = Parent.prototype, 這里找到了, 執行(第二層原型鏈找到)
    child.sayParent();

原理來看寫得有些繁瑣,本身其實是比較簡單的東西。
重點是new的過程,原型prototype和原型鏈__prototype__
也正是new的原理,導致了原型鏈的繼承,本質是生成的對象的__prototype__指向了函數的原型prototype

更復雜的調用繼承之類的,都可以通過這個原理來理解。說白了,原型鏈繼承就是復用了prototype而已。

本例來看,Child中的Parent.call(this)看似沒有必要,但本質上是有區別的。如果去掉這一句,則Child的實例本身將沒有sayAge屬性,而Child.prototype具有sayAge屬性,因此實例的__prototype__具有sayAge屬性,因此還可以執行。

但目的是為了繼承,因此屬性是需要對象上本身持有,而非是通過原型鏈上來訪問,所以加上這一句是原理上的嚴謹要求。可以通過下面的例子來檢驗:

    function Parent() {
        this.sayAge = function() {
            console.log("age is: " + this.age);
        }
    }
    Parent.prototype.sayParent = function(){
        console.log("this is Parent Method");
    }
    
    function Child(firstname){
        Parent.call(this); 
        this.fname = firstname;
        this.age = 40;
        this.saySomething = function() {
            console.log(this.fname);
            this.sayAge();
        }
    }
    
    Child.prototype = new Parent();
    
    var child = new Child("張")
    
    child.saySomething();
    child.sayParent();
    
    console.log(child.hasOwnProperty("sayAge")); // true
    child.sayAge(); //能調用,此時調用的是自身的屬性
    delete child.sayAge; // delete只能刪除自身的屬性,不能刪除原型鏈屬性
    console.log(child.hasOwnProperty("sayAge")); // false,自身沒有這個屬性了
    child.sayAge(); //還能調用,此時調用的是原型鏈上的方法

如果刪掉Parent.call(this), 上面兩句child.hasOwnProperty("sayAge"), 都將返回false

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/88876.html

相關文章

  • 這一次,我們換種姿勢學習 javascript

    摘要:操作符或調用函數時傳入參數的操作都會導致關聯作用域的賦值操作。此外可以使用和來設置對象及其屬性的不可變性級別。忽視這一點會導致許多問題。使用調用函數時會把新對象的屬性關聯到其他對象。 前言 《你不知道的 javascript》是一個前端學習必讀的系列,讓不求甚解的JavaScript開發者迎難而上,深入語言內部,弄清楚JavaScript每一個零部件的用途。本書介紹了該系列的兩個主題:...

    zone 評論0 收藏0
  • JavasScript重難點知識

    摘要:忍者級別的函數操作對于什么是匿名函數,這里就不做過多介紹了。我們需要知道的是,對于而言,匿名函數是一個很重要且具有邏輯性的特性。通常,匿名函數的使用情況是創建一個供以后使用的函數。 JS 中的遞歸 遞歸, 遞歸基礎, 斐波那契數列, 使用遞歸方式深拷貝, 自定義事件添加 這一次,徹底弄懂 JavaScript 執行機制 本文的目的就是要保證你徹底弄懂javascript的執行機制,如果...

    forsigner 評論0 收藏0
  • JavaScript 五十問——從源碼分析 ES6 Class 的實現機制

    摘要:防止類的構造函數以普通函數的方式調用。這個函數的主要作用是通過給類添加方法,其中將靜態方法添加到構造函數上,將非靜態的方法添加到構造函數的原型對象上。 Class是ES6中新加入的繼承機制,實際是Javascript關于原型繼承機制的語法糖,本質上是對原型繼承的封裝。本文將會討論:1、ES6 class的實現細2、相關Object API盤點3、Javascript中的繼承實現方案盤點...

    LeexMuller 評論0 收藏0
  • 前端_JavaScript_面向對象編程

    摘要:面向對象編程對象的原生方法分成兩類自身的方法靜態方法和的實例方法。的靜態方法方法與,參數是對象,返回一個數組,數組的值是改對象自身的所有屬性名區別在于返回可枚舉的屬性,返回不可枚舉的屬性值。 面向對象編程 Objects對象的原生方法分成兩類:Object自身的方法(靜態方法)和Object的實例方法。注意Object是JavaScript的原生對象,所有的其他對象都是繼承自Objec...

    Blackjun 評論0 收藏0
  • JavaScript面向對象的程序設計

    摘要:目錄導語理解對象和面向對象的程序設計創建對象的方式的繼承機制原型對象原型鏈與原型對象相關的方法小結導語前面的系列文章,基本把的核心知識點的基本語法標準庫等章節講解完本章開始進入核心知識點的高級部分面向對象的程序設計,這一部分的內容將會對對象 目錄 導語 1.理解對象和面向對象的程序設計 2.創建對象的方式 3.JavaScript的繼承機制 3.1 原型對象 3.2 原型鏈 3.3 與...

    gitmilk 評論0 收藏0

發表評論

0條評論

最新活動
閱讀需要支付1元查看
<