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

資訊專欄INFORMATION COLUMN

深入JavaScript(一)this & Prototype

The question / 1272人閱讀

摘要:然而事實上并不是。函數本身也是一個對象,但是給這個對象添加屬性并不能影響。一圖勝千言作者給出的解決方案,沒有麻煩的,沒有虛偽的,沒有混淆視線的,原型鏈連接不再赤裸裸。所以是這樣的一個函數以為構造函數,為原型。

注意:本文章是個人《You Don’t Know JS》的讀書筆記。
在看backbone源碼的時候看到這么一小段,看上去很小,其實忽略了也沒有太大理解的問題。但是不知道為什么,我覺得心里很難受。所以我覺得一定要真正解決這個問題。這個問題就是原型。
就是下面這段代碼:

var Surrogate = function(){ this.constructor = child; };
Surrogate.prototype = parent.prototype;
child.prototype = new Surrogate;

看懂了這一段簡單的代碼了嗎?

其實就著backbone的注釋,理解完全沒有問題。但是之后我不小心深究了一下,突然發現自己對于這一個問題的理解還很不透徹。很慚愧,寫了好一陣子的JavaScript,但是一直都是以實用主義的角度來寫的。很多時候真的把JavaScript當成傳統有class的語言來寫了。但是JavaScript是一門很“狡猾”的語言,因為它的很多關鍵字仿佛都在透露自己是傳統面向對象語言,instanceconstructornew等等。然而事實上并不是。解決這個問題的方法就是讀書,我選了《You Don’t Know JS》。我快速過了相關的那一本,被這本書深深震撼到。本文是個人的學習筆記,也希望能幫助到你。

this

this是函數執行的時候,內部產生的一個內部對象。在情況復雜的時候,this的指向會比較難把握。
this的指向常常不明,在書中主要列舉了兩種情況的混淆和四條規則,掌握了這兩者,this就會比較明晰了。(還有很多很復雜的情況需要細致的分析)

兩種混淆

1,this不是函數對象本身。函數本身也是一個對象,但是給這個對象添加屬性并不能影響this。除非foo.call(foo, i),這句代碼的含義是:在foo對象上調用foo函數,并傳遞參數i。這是一個特殊情況。
2,this不是函數內部的作用域。因此在函數內部申明的變量如果不加其他操作,和this根本不會有任何關系。

四條規則

這四條規則只有一個中心,就是call-site。本質上就是指this決定于調用的對象而不是在哪里聲明。
1,直接調用函數。函數內部this會指向全局。this此時為window閉包調用亦是如此。
2,內部綁定調用。如obj.foo()。此時foo中的this指的就是obj對象。注意obj.foo(),不管前面是不是還有其他調用,但是都不會改變this此時為obj
3,直接綁定調用。主要是用了callapply來調用。除此之外還有先bind在調用的方式,這種方式非常強。直接綁定調用的this就是指定的那個參數的對象。
4,new方式調用var bar = new foo() 這一句代碼的作用之一就是把foo函數中的this全部賦到bar上作為新的bar對象的屬性。

優先級

1,一般來說直接綁定調用會比內部綁定調用有更高優先級。
2,new在一定情況下能“覆蓋”bind調用。用這個特性可以實現函數currying化。(函數傳入多個參數,在bind的時候傳入固定的變量)

function foo(val) {
    this.val = val;
}
var obj = {};
var bar = foo.bind(obj);
bar("p1");
var baz = new bar("p2")
console.log(baz.val); // p2
new & Object.create

JavaScript沒有類,也不能創建實例。但是語法上確實非常非常面向對象,讓人誤解。new就是總被誤解。

var bar = new foo();

下面詳述這一句代碼執行的效果。這非常重要。
1,執行foo()函數。是“構造方式調用”。注意,JavaScript里面并沒有真正的構造函數。
2,連接foo.prototype和新對象bar[[prototype]]。(相當于把foo.prototype整體搬到(引用)bar.__proto__里面)
3,把foo中的內部對象this的屬性給bar
4,foo如果有返回對象就返回那個對象,沒有就自動返回一個新的對象。對象特征如2,3所述。
事實上,new做得事太多,很多時候令人討厭。
注意:barfoo函數對象本身的屬性沒有關系。

在經典的教材上,JavaScript的“繼承”常常使用下面的代碼:

Bar.prototype = new Foo();

這句代碼很經典,但是并不好。它固然能夠完成原型鏈的連接,但是也產生了很多不必要的麻煩。Bar.prototype上會帶上Foothis,副作用大。因此書上建議是這樣做來完成繼承的:

Bar.prototype = Object.create(Foo.prototype);

A = Object.create(B)的作用是把B對象的屬性添加到A__proto__上面,然后A[[prototype]]B的連接。有個比較“直觀”的說法,就是把B的“屬性”,添加到A.__proto__上面,然后把B.__proto__也添加進去(原型鏈延長的不嚴謹說法)。試著在chrome里面console一下,就會發現此時的A只有一個__proto__屬性,里面是B的屬性和B.__proto__。這樣就很好地完成了“繼承”,而且也沒有副作用了。下面提供一個降級寫法(原理很簡單。按照之前的幾條規則可以很輕易地讀懂):

// Object.create
if(!Object.create) {
    Object.create = function(o) {
        function F(){};
        F.prototype = o;
        return new F();
    }
}

還需要注意的是constructor屬性。如果對象是函數,這個屬性會自動出現在函數的prototype里面,但有時候會被覆蓋。

原型

prototype是函數對象的一個屬性。其實可以理解成比較特殊的一個屬性,一個對象。這個屬性在用構造器方式調用(new)的時候就用來連接新對象。連接到最后就是Object.prototype,這是每一個對象(不包括null)中__proto__的盡頭,原型鏈的盡頭。可以想象,對象的聲明是new Object(),那么新的對象原型鏈自然就會有Object.prototype了。如果想擺脫這個Object.prototype,可以用Object.create(null)
經常有這種情況,調用一個對象的屬性的時候,如果在本身找不到就會沿著原型鏈找。直觀而不嚴謹地說,就是從__proto__一直找下去。這也揭露了a instanceof foo的本質。就是沿著原型鏈找,看看在a的原型鏈上有沒有foo.prototype的存在,有就返回trueinstanceof這個英文很誤導,因為JavaScript里面根本上就算不上有實例這樣的東西。

OLOO

作者對于JavaScript的面向對象有一個非常驚艷的解決方案,在那之前先看看以前的方案是怎么做的。

function Foo(who) {
    this.me = who;
}
Foo.prototype.identify = function() {
    return "I am " + this.me;
};

function Bar(who) {
    Foo.call( this, who );
}
Bar.prototype = Object.create( Foo.prototype );

Bar.prototype.speak = function() {
    alert( "Hello, " + this.identify() + "." );
};

var b1 = new Bar( "b1" );
var b2 = new Bar( "b2" );

b1.speak();
b2.speak();

一圖勝千言:

作者給出的解決方案OLOOobjects-linked-to-other-objects),沒有麻煩的new,沒有虛偽的constructor,沒有混淆視線的call, apply, bind,原型鏈連接不再赤裸裸。感覺真心很棒(注意一點,JavaScript對象的方法其實是不是“屬于”一個對象值得商榷,因為所謂方法其實和這個對象關系并沒有想象中大):

var Foo = {
    init: function(who) {
        this.me = who;
    },
    identify: function() {
        return "I am " + this.me;
    }
};

var Bar = Object.create( Foo );

Bar.speak = function() {
    alert( "Hello, " + this.identify() + "." );
};

var b1 = Object.create( Bar );
b1.init( "b1" );
var b2 = Object.create( Bar );
b2.init( "b2" );

b1.speak();
b2.speak();

仍然是一圖勝千言:

最后來講講這個:

var Surrogate = function(){ this.constructor = child; };
Surrogate.prototype = parent.prototype;
child.prototype = new Surrogate;

很好懂了吧。構造形式調用Surrogate函數,把this上的屬性交給child.prototype,這里是constructor;把Surrogate.prototype的內容搬到child.prototype.__proto__上面。而Surrogate.prototype引用自parent.prototype。所以child是這樣的一個函數:以child為構造函數,parent.prototype為原型。

總結:

這個問題是老生常談的問題了,但是我覺得對于每一個寫JavaScript的人來說,這個問題是永遠避不開的。最后再次推薦《You Don’t Know JS》這一套開源書。可以毫不夸張地說,這是自紅寶書和犀牛書之后講JavaScript的最好書了。深度深得恰到好處,語言和例子清晰簡明,我還要繼續學習。

有關 this & Object Prototypes ,書的內容遠遠比我這篇文章豐富精彩,去讀吧。(我也要復反復讀)

如果有任何錯誤請輕噴,相互學習~

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

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

相關文章

  • 《你不知道的javascript》筆記_對象&原型

    摘要:上一篇你不知道的筆記寫在前面這是年第一篇博客,回顧去年年初列的學習清單,發現僅有部分完成了。當然,這并不影響年是向上的一年在新的城市穩定連續堅持健身三個月早睡早起游戲時間大大縮減,學會生活。 上一篇:《你不知道的javascript》筆記_this 寫在前面 這是2019年第一篇博客,回顧去年年初列的學習清單,發現僅有部分完成了。當然,這并不影響2018年是向上的一年:在新的城市穩定、...

    seasonley 評論0 收藏0
  • javascript中的constructor&&prototype

    摘要:于是退而求其次叫為類的構造函數。如果這個函數被用在創建自定義對象的場景中,我們稱這個函數為構造函數。遇到的問題始終指向創建當前對象的構造函數。 Object.constructor,prototype 對象的prototype和constructor是兩個重要的屬性,他們總是成對出現,提到constructor的地方,不得不涉及到另外一個非常重要的屬性prototype,它是js中基于...

    huaixiaoz 評論0 收藏0
  • 溫故js系列(15)-原型&原型鏈&原型繼承

    摘要:給添加屬性給的原型對象添加屬性原型鏈在中,每個對象都有一個屬性,其保存著的地址就構成了對象的原型鏈。實例變量實例函數原型鏈繼承有了原型鏈,就可以借助原型鏈實現繼承。是中唯一一個處理屬性但是不查找原型鏈的函數。 前端學習:教程&開發模塊化/規范化/工程化/優化&工具/調試&值得關注的博客/Git&面試-前端資源匯總 歡迎提issues斧正:原型&原型鏈&原型繼承 JavaScript-原...

    Ethan815 評論0 收藏0
  • JavaScript - 原型&原型鏈

    摘要:可以看出,這個查找過程是一個鏈式的查找,每個對象都有一個到它自身原型對象的鏈接,這些鏈接組件的整個鏈條就是原型鏈。原型的構建字面量方式當通過字面量方式創建對象時,它的原型就是。 面向對象 JavaScript沒有類(class)的概念的(ES6 中的class也只不過是語法糖,并非真正意義上的類),而在JavaScript中,在 JavaScript 中,除了 String, Numb...

    wean 評論0 收藏0
  • 圖解javascript原型&原型鏈

    我們在學習javascript時,經常會聽到萬物皆對象,但是呢,其實萬物皆對象的對象也有區別。分為普通對象和函數對象。1.對象分為函數對象和普通對象? ??通過new Function()創建的對象都是函數對象,其他的都是普通對象。showImg(https://segmentfault.com/img/bVbtWre?w=526&h=252); 2.構造函數而提到new關鍵字,我們不得不提到構造...

    sutaking 評論0 收藏0

發表評論

0條評論

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