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

資訊專欄INFORMATION COLUMN

js回顧:原型鏈

call_me_R / 2538人閱讀

摘要:原型鏈原型鏈實(shí)際上是中的實(shí)現(xiàn)繼承的機(jī)制,在搞懂原型鏈之前首先要搞懂幾個(gè)概念,普通對(duì)象和函數(shù)對(duì)象,構(gòu)造函數(shù),對(duì)于很多人來說是混雜不清的概念,但是想要弄清楚原型鏈我們必須了解什么是首先,只能在存在與函數(shù)中其次,其實(shí)是當(dāng)前函數(shù)所在上下文環(huán)境,再簡(jiǎn)

原型鏈

原型鏈實(shí)際上是JavaScript中的實(shí)現(xiàn)繼承的機(jī)制,在搞懂原型鏈之前首先要搞懂幾個(gè)概念:this,普通對(duì)象和函數(shù)對(duì)象,構(gòu)造函數(shù),new

this

this對(duì)于很多人來說是混雜不清的概念,但是想要弄清楚原型鏈我們必須了解什么是this

首先,this只能在存在與函數(shù)中

其次,this其實(shí)是當(dāng)前函數(shù)所在上下文環(huán)境,再簡(jiǎn)單一點(diǎn)也可以理解為this返回一個(gè)當(dāng)前函數(shù)所在的對(duì)象,也就是說想要知道this是什么我們只需要關(guān)注是誰調(diào)用了this所在的函數(shù)就可以了

如下邊的代碼zhao.sayName()是zhao調(diào)用的sayName函數(shù)所以sayName中的this自然指的就是zhao這個(gè)對(duì)象,而下方 var liName = zhao.sayName語句是將sayName這個(gè)函數(shù)賦值給liName,調(diào)用liName就相當(dāng)于在最頂層也就是window下直接調(diào)用sayName,this的指向自然就是window這個(gè)最頂層對(duì)象

    var name = "Li"
    var zhao = {
        name: "Zhao",
        sayName: function () {
            console.log(this.name);
        }
    }
    zhao.sayName() // Zhao
    var liName = zhao.sayName;
    liName() // Li
普通對(duì)象與函數(shù)對(duì)象

JavaScript中一切都可以看作對(duì)象,但是實(shí)際上對(duì)象也是有區(qū)別的,對(duì)象分為普通對(duì)象函數(shù)對(duì)象

    // 普通對(duì)象
    var o1 = {}
    var o2 = new Object()
    var o3 = new f1()
    // 函數(shù)對(duì)象
    function f1(){}
    var f2 = function(){}
    var f3 = new Function()

    console.log(typeof f1); //function
    console.log(f1.prototype); //true
    console.log(typeof f2); //function
    console.log(f2.prototype); //true
    console.log(typeof f3); //function
    console.log(f3.prototype); //true

    console.log(typeof o1); //object
    console.log(o1.prototype); //undefined
    console.log(typeof o2); //object
    console.log(o2.prototype); //undefined
    console.log(typeof o3); //object
    console.log(o3.prototype); //undefined

凡是通過function構(gòu)建的對(duì)象都是函數(shù)對(duì)象,并且只有函數(shù)對(duì)象才有prototype屬性,普通對(duì)象沒有

prototype 原型

prototype又是什么呢?

當(dāng)我們創(chuàng)建函數(shù)的時(shí)候,編譯器會(huì)自動(dòng)為該函數(shù)創(chuàng)建一個(gè)prototype屬性,這和屬性指向一個(gè)包含constructor屬性的對(duì)象,而這個(gè)屬性又默認(rèn)指回原函數(shù),讀起來有點(diǎn)繞對(duì)吧,大概是這樣的

    function Person() {
    //    prototype = {
    //        constructor: Person,
    //    }
    }

每個(gè)函數(shù)對(duì)象都有一個(gè)prototype(原型)屬性,在我看來prototype屬性的意義:

創(chuàng)建對(duì)象的模板

公開的共享空間

這兩點(diǎn)等學(xué)習(xí)了下邊new命令你就會(huì)明白了

constructor 構(gòu)造函數(shù)

函數(shù)對(duì)象的一種用法就是構(gòu)造函數(shù),通過構(gòu)造函數(shù)可以構(gòu)建一個(gè)函數(shù)對(duì)象的實(shí)例(普通對(duì)象)

    function Person(name, age ){
        this.name = name;
        this.age = age;
        this.sayHello = function(){
            console.log(`Hello! my name is ${this.name}`);
        };
    }

    var person1 = new Person("kidder", 28);
    person1.sayHello(); // Hello! my name is kidder
    console.log(person1.constructor); //[Function:Person]

按照慣例,構(gòu)造函數(shù)的命名以大寫字母開頭,非構(gòu)造函數(shù)以小寫字母開頭,通過構(gòu)造函數(shù)構(gòu)造的普通對(duì)象都會(huì)有一個(gè)constructor(構(gòu)造函數(shù))屬性,該屬性指向構(gòu)造該對(duì)象的構(gòu)造函數(shù)

new命令 new命令的工作機(jī)制

創(chuàng)建一個(gè)空對(duì)象作為要返回對(duì)象的實(shí)例

將這個(gè)空對(duì)象的原型(__ proto __)指向構(gòu)造函數(shù)的prototype屬性

將這個(gè)空對(duì)象賦值給構(gòu)造函數(shù)內(nèi)部的this

執(zhí)行構(gòu)造函數(shù)內(nèi)部的代碼

原型鏈

下面我們來看看構(gòu)造函數(shù)構(gòu)建一個(gè)普通對(duì)象的時(shí)候發(fā)生了什么

    var Person = function (name) {
        this.name = name;
        this.age = 18;
    };
    Person.prototype.sayHello = function(){
        console.log(`Hello! my name is ${this.name}`);
    };
    var li = new Person("Li");
    console.log(li.name); // Li
    console.log(li.age); // 18
    li.sayHello(); // Hello! my name is Li

創(chuàng)建一個(gè)空對(duì)象作為要返回對(duì)象的實(shí)例

    {}

將這個(gè)空對(duì)象的原型(__ proto __)指向構(gòu)造函數(shù)的prototype屬性

    {
        __proto__:Person.prototype;
    }

將這個(gè)空對(duì)象賦值給構(gòu)造函數(shù)內(nèi)部的this

    this = {
        __proto__:Person.prototype;
    }

執(zhí)行構(gòu)造函數(shù)內(nèi)部的代碼

   this = {
        __proto__:Person.prototype;
       name: "Li";
       age: 18;
   }

所以li這個(gè)對(duì)象中只有name和age兩個(gè)屬性,為什么li.sayHello()會(huì)輸出Hello! my name is Li呢?

這就是原型鏈,當(dāng)給定的屬性在當(dāng)前對(duì)象中找不到的情況下,會(huì)沿著__proto__這個(gè)屬性一直向?qū)ο蟮纳嫌稳ふ遥钡絖_proto__這個(gè)屬性指向null為止,如果找到指定屬性,查找就會(huì)被截?cái)啵V?/p>

上面這張圖是整個(gè)JavaScript的原型鏈體系,為了讓這張圖更直觀所以我將構(gòu)造函數(shù)的prototype屬性多帶帶提了出來,恩,其實(shí)畫在構(gòu)造函數(shù)內(nèi)部也可,但同時(shí)因?yàn)閷?duì)象是引用類型,所以這樣畫也沒毛病吧

_ proto _ 和 prototype

這兩個(gè)屬性經(jīng)常會(huì)被我們混淆,那么我們回過頭再來總結(jié)一下

prototype:只有函數(shù)對(duì)象才具有的屬性,它用來存放的是構(gòu)造函數(shù)希望構(gòu)建的實(shí)例具有的共享的屬性和方法,主要用于構(gòu)造函數(shù)的實(shí)例化

_proto_ : 所有對(duì)象都具有的屬性,它指向的是當(dāng)前對(duì)象在原型鏈上的上級(jí)對(duì)象,主要作用是讓編譯器在由__proto__這個(gè)屬性構(gòu)成的原型鏈上查找特定的屬性和方法

補(bǔ)充 prototype的共享屬性
    var Person = function (name) {
        this.name = name;
        this.age = 18;
    };
    Person.prototype.sayHello = function(){
        console.log(`Hello! my name is ${this.name}`);
    };
    var li = new Person("Li");

    var Person1 = function () {
    };
    Person.prototype.name = "Li"
    Person.prototype.age = 18
    Person.prototype.sayHello = function(){
        console.log(`Hello! my name is ${this.name}`);
    };

    var Li = new Person1();

關(guān)于Person和Person1兩種構(gòu)造函數(shù)的寫法有什么不同呢?

一般來說寫在prototype原型對(duì)象中的屬性和方法都是公用的,也就是說寫在構(gòu)造函數(shù)中的屬性在構(gòu)建普通對(duì)象的時(shí)候,都會(huì)在新對(duì)象中重新定義,也就是從內(nèi)存的角度來說又會(huì)多占用一些內(nèi)存空間,所以我們將構(gòu)造函數(shù)的所有屬性和方法都寫在prototype原型中不好嗎?

但是原型函數(shù)也是有缺點(diǎn)的:

不夠靈活

    var Person = function () {
    };
    Person.prototype.name = "Li"
    Person.prototype.age = 18
    Person.prototype.sayHello = function(){
        console.log(`Hello! my name is ${this.name}`);
    };

    var li = new Person();
    var zhao = new Person();

這種方式構(gòu)造的所有對(duì)象都是一個(gè)模板,雖然我們也可以在當(dāng)前對(duì)象下進(jìn)行修改,但這樣一點(diǎn)也不優(yōu)雅,不規(guī)整,而且從某種意義上來說也是對(duì)內(nèi)存的浪費(fèi)

對(duì)于引用類型的修改會(huì)被全部共享

    var Person = function () {
    };
    Person.prototype.name = "Li"
    Person.prototype.age = 18
    Person.prototype.friends = ["ZhangSan", "LiSi"]
    Person.prototype.sayHello = function(){
        console.log(`Hello! my name is ${this.name}`);
    };

    var li = new Person();
    var zhao = new Person();
     li.friends.push("WangWu");
    console.log(zhao.friends); // [ "ZhangSan", "LiSi", "WangWu" ]

在JavaScript中,基本類型的修改可以明確的通過創(chuàng)建或修改在當(dāng)前對(duì)象下的屬性對(duì)原型鏈進(jìn)行截?cái)啵窍駭?shù)組,對(duì)象這種引用類型的值雖然也可以通過在當(dāng)前對(duì)象中創(chuàng)建該屬性來對(duì)原型鏈進(jìn)行截?cái)啵且徊蛔⒁饩涂赡軙?huì)出現(xiàn)上面這種情況直接對(duì)原型進(jìn)行了修改

構(gòu)造函數(shù)與原型相結(jié)合

所以,用構(gòu)造函數(shù)來定義實(shí)例屬性,用原型定義方法和共享的屬性,這樣寫就比較優(yōu)雅了

    function Person(name, age){
        this.name = name;
        this.age = age;
        this.friends = ["ZhangSan", "LiSi"];
    }
    Person.prototype.sayHello = function(){
        console.log(`Hello! my name is ${this.name},${this.age}歲了`);
    };
    var li = new Person("li", 18);
    var zhao = new Person("zhao", 16);
    li.sayHello();
    // Hello! my name is li, 18歲了
    zhao.sayHello();
    // Hello! my name is zhao,16歲了
    li.friends.push("WangWu");
    console.log(zhao.friends);
    // [ "ZhangSan", "LiSi" ]
創(chuàng)建對(duì)象的幾種方式

構(gòu)造函數(shù)方式

法一用構(gòu)造函數(shù)構(gòu)造一個(gè)新對(duì)象

    var A = function () { };
    var a = new A();
    console.log(a.constructor); // [Function:A]
    console.log(a.__proto__ === A.prototype); //true

字面量方式

法二的本質(zhì)來說和法一是一樣的,就是隱式調(diào)用原生構(gòu)造函數(shù)Object來構(gòu)造新對(duì)象

    var a = {};
    // var a = new Object();
    console.log(a.constructor); // [Function:Object]
    console.log(a.__proto__ === Object.prototype); //true

create方式

法三Object.create是以一個(gè)普通對(duì)象為模板創(chuàng)建一個(gè)新對(duì)象

    var a1 = {a:1}
    var a2 = Object.create(a1);
    console.log(a2.constructor); // [Function:Object]
    console.log(a2.__proto__ === a1);// true
    console.log(a2.__proto__ === a1.prototype); //false

所以除了Object.create創(chuàng)建對(duì)象的方式,可以說:__ proto __ === constructor.prototype;

constructor

前面我們說道prototype的時(shí)候進(jìn)行原型屬性的賦值的時(shí)候,采用的是逐項(xiàng)賦值,那么當(dāng)我直接將對(duì)象賦值給prototype屬性的時(shí)候會(huì)發(fā)生什么呢?

    function Person() { }
    Person.prototype = {
        name : "Li",
        age : 18,
        sayHello : function () {
            console.log(`Hello! my name is ${this.name},${this.age}歲了`);
        }
    };
    var li = new Person();
    console.log(li instanceof Object);        // true
    console.log(li instanceof Person);        // true
    console.log(li.constructor === Person);    // false
    console.log(li.constructor === Object);    // true
    console.log(Person.prototype.constructor);  // Object

這時(shí)候我們就發(fā)現(xiàn)我們構(gòu)建的li對(duì)象的constructor不再指向它的構(gòu)造函數(shù)Person,而是指向了Object,并且Person原型Person.prototype的constructor指向也指向了Object,這是什么原因呢?

其實(shí),根源出現(xiàn)在Person.prototype上,上邊我們提到過,其實(shí)我們?cè)趯憳?gòu)造函數(shù)的時(shí)候?qū)嶋H上是這樣的

    function Person() {
    // prototype = {
    //    constructor : Person
    // }
    }

當(dāng)我們構(gòu)建Person構(gòu)造函數(shù)的時(shí)候,編譯器會(huì)自動(dòng)生成一個(gè)帶有指向Person的constructor屬性的對(duì)象,并把這個(gè)對(duì)象賦值給Person.prototype,我們又知道js中對(duì)象是引用類型,當(dāng)我們使用Person.prototype.name=...的時(shí)候?qū)嶋H上是對(duì)這個(gè)對(duì)象的修改,而使用Person.prototype={...}實(shí)際上是將這個(gè)屬性原本的指針指向了另一個(gè)新創(chuàng)建的對(duì)象而不是原來編譯器自動(dòng)創(chuàng)建的那個(gè):

而li的constructor屬性自然是繼承自Person.prototype,所以constructor自然也就跟著改變了,如果在編程的過程中constructor這個(gè)屬性很重要的話可以通過下面的方式

    function Person() { }
    Person.prototype = {
        constructor:Person
        name : "Li",
        age : 18,
        sayHello : function () {
            console.log(`Hello! my name is ${this.name},${this.age}歲了`);
        }
    };
    
    var li = new Person();
    console.log(li instanceof Object);        // true
    console.log(li instanceof Person);        // true
    console.log(li.constructor === Person);    // true
    console.log(li.constructor === Object);    // false
    console.log(Person.prototype.constructor);  // Person
結(jié)語:

參考:《JavaScript高級(jí)程序設(shè)計(jì)》

這是我對(duì)JS原型鏈部分的總結(jié)與思考,也是我寫的第一篇這么正式的技術(shù)文檔,如有紕漏之處,歡迎大家批評(píng)指正

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/102330.html

相關(guān)文章

  • 關(guān)于javascript的原型原型,看我就夠了(一)

    摘要:要用作原型的對(duì)象。函數(shù)對(duì)象可以創(chuàng)建普通對(duì)象,這個(gè)我們上面講過了回顧一下這是一個(gè)自定義構(gòu)造函數(shù)普通對(duì)象沒法創(chuàng)建函數(shù)對(duì)象,凡是通過創(chuàng)建的對(duì)象都是函數(shù)對(duì)象,其他都是普通對(duì)象通常通過創(chuàng)建,可以通過來判斷。 關(guān)于js的原型和原型鏈,有人覺得這是很頭疼的一塊知識(shí)點(diǎn),其實(shí)不然,它很基礎(chǔ),不信,往下看要了解原型和原型鏈,我們得先從對(duì)象說起 創(chuàng)建對(duì)象 創(chuàng)建對(duì)象的三種方式: 對(duì)象直接量 通過對(duì)象直接量創(chuàng)建...

    MoAir 評(píng)論0 收藏0
  • 前端面試回顧(1)---javascript的面向?qū)ο?/b>

    摘要:每個(gè)類有三部分構(gòu)成第一部分是構(gòu)造函數(shù)內(nèi),供實(shí)例對(duì)象化復(fù)制用。第二部分是構(gòu)造函數(shù)外,直接通過點(diǎn)語法添加,供類使用,實(shí)例化對(duì)象訪問不到。組合繼承還有一個(gè)要注意的地方在代碼處,將子類原型的屬性指向子類的構(gòu)造函數(shù)。 前言 前一陣面試,過程中發(fā)現(xiàn)問到一些很基礎(chǔ)的問題時(shí)候,自己并不能很流暢的回答出來。或者遇到一些基礎(chǔ)知識(shí)的應(yīng)用,由于對(duì)這些點(diǎn)理解的不是很深入,拿著筆居然什么都寫不出來,于是有了回顧一...

    animabear 評(píng)論0 收藏0
  • JS面向?qū)ο蟮某绦蛟O(shè)計(jì)之繼承的實(shí)現(xiàn) - 原型

    摘要:簡(jiǎn)單回顧一下構(gòu)造函數(shù)原型和實(shí)例對(duì)象之間的關(guān)系每個(gè)構(gòu)造函數(shù)都有一個(gè)原型對(duì)象。找到生成構(gòu)造函數(shù)的原型對(duì)象的構(gòu)造函數(shù),搜索其原型對(duì)象,找到了。 JS面向?qū)ο蟮某绦蛟O(shè)計(jì)之繼承的實(shí)現(xiàn) - 原型鏈 前言:最近在細(xì)讀Javascript高級(jí)程序設(shè)計(jì),對(duì)于我而言,中文版,書中很多地方翻譯的差強(qiáng)人意,所以用自己所理解的,嘗試解讀下。如有紕漏或錯(cuò)誤,會(huì)非常感謝您的指出。文中絕大部分內(nèi)容引用自《JavaS...

    zhaochunqi 評(píng)論0 收藏0
  • js溫故而知新7(面向?qū)ο缶幊?——學(xué)習(xí)廖雪峰的js教程

    摘要:不區(qū)分類和實(shí)例的概念,而是通過原型來實(shí)現(xiàn)面向?qū)ο缶幊獭P聞?chuàng)建的的原型鏈?zhǔn)且簿褪钦f,的原型指向函數(shù)的原型。最后,創(chuàng)建一個(gè)對(duì)象代碼和前面章節(jié)完全一樣小明繼承用定義對(duì)象的另一個(gè)巨大的好處是繼承更方便了。 JavaScript不區(qū)分類和實(shí)例的概念,而是通過原型(prototype)來實(shí)現(xiàn)面向?qū)ο缶幊獭?原型是指當(dāng)我們想要?jiǎng)?chuàng)建xiaoming這個(gè)具體的學(xué)生時(shí),我們并沒有一個(gè)Student類型可用...

    Jaden 評(píng)論0 收藏0
  • 關(guān)于原型中constructor、prototype及__proto__的問題

    摘要:最近看到一個(gè)關(guān)于原型鏈的問題,回顧一下原型鏈的知識(shí)點(diǎn)。說說為什么為什么是。首先不是自身的屬性,而是原型鏈上的,即的原型中。類似通過這樣來找到的值。,不是復(fù)制了對(duì)象,而是把指向了,所以對(duì)的修改會(huì)影響到的值。再看看這張圖一切都明朗了。 最近看到一個(gè)關(guān)于原型鏈的問題,回顧一下原型鏈的知識(shí)點(diǎn)。 function person(name) { this.name = name; ...

    alanoddsoff 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

call_me_R

|高級(jí)講師

TA的文章

閱讀更多
最新活動(dòng)
閱讀需要支付1元查看
<