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

資訊專欄INFORMATION COLUMN

關(guān)於Javascript中的new運(yùn)算符,構(gòu)造函數(shù)與原型鏈一些理解

cikenerd / 1922人閱讀

摘要:前言文章主要基于高級(jí)程序設(shè)計(jì)總結(jié)的基本重寫了全文補(bǔ)充知識(shí)點(diǎn)新增實(shí)例優(yōu)化排版新增檢測(cè)方法技巧用法構(gòu)造函數(shù)創(chuàng)建一個(gè)用護(hù)定義的對(duì)象類型的實(shí)例或具有構(gòu)造函數(shù)的內(nèi)置對(duì)象類型之一命令執(zhí)行構(gòu)造函數(shù)返回一個(gè)實(shí)例對(duì)象構(gòu)造函數(shù)一個(gè)指定對(duì)象實(shí)例的類型的函數(shù)傳慘一

前言

文章主要基于<< Javascrpt 高級(jí)程序設(shè)計(jì)3 >>總結(jié)的!!!
PS: 2018/05/09 基本重寫了全文,補(bǔ)充知識(shí)點(diǎn),新增實(shí)例,優(yōu)化排版
PS: 2018/05/11 新增檢測(cè)方法,技巧用法

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

創(chuàng)建一個(gè)用護(hù)定義的對(duì)象類型的實(shí)例或具有構(gòu)造函數(shù)的內(nèi)置對(duì)象類型之一

new命令: 執(zhí)行構(gòu)造函數(shù)返回一個(gè)實(shí)例對(duì)象

構(gòu)造函數(shù)(constructor): 一個(gè)指定對(duì)象實(shí)例的類型的函數(shù)

傳慘(arguments): 一個(gè)用來(lái)被構(gòu)造函數(shù)調(diào)用的慘數(shù)列表

注意點(diǎn)幾個(gè):

默認(rèn)構(gòu)造函數(shù)首字母大寫區(qū)分函數(shù)類型

在不傳遞任何慘數(shù)的情況new constructor可以省略括號(hào)

構(gòu)造函數(shù)與其他函數(shù)的唯一區(qū)別: 就在于調(diào)用它們的方式不同.(任何函數(shù),只要通過(guò) new 操作符來(lái)調(diào)用,那它就可以作為構(gòu)造函數(shù);而任何函數(shù),如果不通過(guò) new 操作符來(lái)調(diào)用,那它跟普通函數(shù)也不會(huì)有什麼兩樣)

使用構(gòu)造函數(shù)的主要問(wèn)題,就是每個(gè)方法都要在每個(gè)實(shí)例上重新創(chuàng)建一遍

new存在的意義在于它實(shí)現(xiàn)了javascript中的繼承,而不僅僅是實(shí)例化了一個(gè)對(duì)象

這是基本用法,大家都懂的,然后我們往深層次里挖掘下底層原理怎麼運(yùn)作的.
假設(shè)有個(gè)函數(shù)

function Person(name) {
  this.name = name || "mike",
    this.getAge = function () {
      console.log(10);
    }
}

var man = new Person;
var women = new Person("tracy")

console.log(man.name, women.name) // mike tracy

當(dāng)代碼執(zhí)行時(shí)會(huì)經(jīng)過(guò)幾個(gè)步驟:

以下是我基于JS高程3總結(jié)的:

一個(gè)新的空對(duì)象被創(chuàng)建

創(chuàng)建執(zhí)行的時(shí)候,將構(gòu)造函數(shù)的作用域賦給新對(duì)象(因此 this 就指向了這個(gè)新對(duì)象)

執(zhí)行構(gòu)造函數(shù)中的代碼(為這個(gè)新對(duì)象添加屬性)等初始化工作

如果構(gòu)造函數(shù)返回了一個(gè)“對(duì)象”,那麼這個(gè)對(duì)象會(huì)取代整個(gè)new出來(lái)的結(jié)果.如果構(gòu)造函數(shù)沒有返回對(duì)象,那麼new出來(lái)的結(jié)果為步驟1創(chuàng)建的對(duì)象,(ps:一般情況下構(gòu)造函數(shù)不返回任何值,如果想覆蓋這個(gè)返回值,可以選擇返回一個(gè)普通對(duì)象.);

以下是原版:

創(chuàng)建一個(gè)新對(duì)象

將構(gòu)造函數(shù)的作用域賦給新對(duì)象(因此 this 就指向了這個(gè)新對(duì)象)

執(zhí)行構(gòu)造函數(shù)中的代碼(為這個(gè)新對(duì)象添加屬性)

返回新對(duì)象.

下面詳細(xì)舉例
1、如果構(gòu)造函數(shù)不返回任何值則按照其他語(yǔ)言一樣返回實(shí)例化對(duì)象(即步驟1創(chuàng)建的對(duì)象).

function Person() { }
var man = new Person();
console.log(man) // Person {}

2、如果構(gòu)造函數(shù)返回的是基本類型 (string, number, boolean, null,undefined) 也按照其他語(yǔ)言一樣返回實(shí)例化對(duì)象(即步驟1創(chuàng)建的對(duì)象).如果你們還搞不懂基本類型跟引用對(duì)象的區(qū)別,可以參考我之前寫的文章關(guān)於javascript基本類型和引用類型小知識(shí)

function Person() {
  return "我是基本類型"
}

var man = new Person();
console.log(man)//Person {}

3、若返回值是引用類型,則實(shí)際返回值為這個(gè)引用類型.

function Person() {
  return {
    age: 18
  }
}

var man = new Person();
console.log(man) //Object {age: 18}

初學(xué)者特別應(yīng)該注意的是他們之間是不同的,所謂的構(gòu)造函數(shù)是創(chuàng)建一個(gè)用戶定義的對(duì)象類型的實(shí)例或具有構(gòu)造函數(shù)的內(nèi)置對(duì)象類型之一

正常來(lái)說(shuō)構(gòu)造函數(shù)不需要有返回值的,可以認(rèn)為構(gòu)造函數(shù)和普通函數(shù)的最大差別就是:構(gòu)造函數(shù)中沒有return語(yǔ)句,普通函數(shù)可以有return語(yǔ)句;構(gòu)造函數(shù)中會(huì)使用this關(guān)鍵字定義成員變量和成員方法,普通的函數(shù)不會(huì)使用this關(guān)鍵字定義成員變量和方法.
像第二種情況即使返回基本類型也會(huì)被忽略掉,只有選擇返回一個(gè)普通對(duì)象才會(huì)取代整個(gè)new出來(lái)的結(jié)果

原型對(duì)象(prototype)

每個(gè)函數(shù)都有一個(gè) prototype 屬性, prototype 就是指向通過(guò)調(diào)用構(gòu)造函數(shù)而創(chuàng)建的那個(gè)對(duì)象實(shí)例的原型對(duì)象,作用是可以讓所有對(duì)象實(shí)例共享它所包含的屬性和方法.
JavaScript中一切皆對(duì)象,每個(gè)對(duì)象都是繼承自另一個(gè)對(duì)象,所以對(duì)象都有自己的原型對(duì)象(除了null以外).
所以除了在構(gòu)建函數(shù)內(nèi)部定義屬性方法共享之外,我們還可以在構(gòu)造函數(shù)的原型對(duì)象上添加共享的自定義屬性方法.

function Person() { }
//原型鏈添加函數(shù)
Person.prototype.getAge = function () {
  console.log(18)
}

//實(shí)例化
var man = new Person(),
  women = new Person();

man.getAge() // 18
women.getAge() // 18

有一種情況是對(duì)象實(shí)例自身已經(jīng)賦有同名屬性方法會(huì)覆蓋 prototype 上的屬性方法.這個(gè)認(rèn)知是不準(zhǔn)確的,下面的原型鏈會(huì)講到這部分.

function Person() { }
//原型鏈添加函數(shù)
Person.prototype.getAge = function () {
  console.log(18)
}

//實(shí)例化
var man = new Person();
man.getAge = function () {
  console.log(81)
}

man.getAge() // 81

還有一種情況是在構(gòu)造函數(shù)的原型對(duì)象上添加共享的自定義屬性方法并且實(shí)例化對(duì)象之后,再次修改原型對(duì)象上的方法.同樣會(huì)影響到輸出結(jié)果,依然下面的原型鏈會(huì)講到這部分.

function Person() { }
//原型鏈添加函數(shù)
Person.prototype.getAge = function () {
  console.log(18)
}

//實(shí)例化
var man = new Person();
//修改原型鏈自定義函數(shù)
Person.prototype.getAge = function () {
  console.log(81)
}

man.getAge() // 81
原型鏈

下面引出JS高程三解析片段----------

理解原型對(duì)象(關(guān)鍵詞 prototype, constructor, __proto__)
無(wú)論什麼時(shí)候,只要?jiǎng)?chuàng)建了一個(gè)新函數(shù),就會(huì)根據(jù)一組特定的規(guī)則為該函數(shù)創(chuàng)建一個(gè) prototype 屬性,這個(gè)屬性指向函數(shù)的原型對(duì)象.

在默認(rèn)情況下,所有原型對(duì)象都會(huì)自動(dòng)獲得一個(gè) constructor(構(gòu)造函數(shù))屬性,這個(gè)屬性包含一個(gè)指向 prototype 屬性所在函數(shù)的指針.

就拿前面的例子來(lái)說(shuō),Person.prototype.constructor 指向 Person .而通過(guò)這個(gè)構(gòu)造函數(shù),我們還可繼續(xù)為原型對(duì)象添加其他屬性和方法.創(chuàng)建了自定義的構(gòu)造函數(shù)之后,其原型對(duì)象默認(rèn)只會(huì)取得 constructor 屬性;至于其他方法,則都是從 Object 繼承而來(lái)的.

當(dāng)調(diào)用構(gòu)造函數(shù)創(chuàng)建一個(gè)新實(shí)例后,該實(shí)例的內(nèi)部將包含一個(gè)指針(內(nèi)部屬性),指向構(gòu)造函數(shù)的原型對(duì)象.

ECMA-262 第 5 版中管這個(gè)指針叫 [[Prototype]] .雖然在腳本中沒有標(biāo)準(zhǔn)的方式訪問(wèn) [[Prototype]] ,但 Firefox、Safari 和 Chrome 在每個(gè)對(duì)象上都支持一個(gè)屬性__proto__ ;而在其他實(shí)現(xiàn)中,這個(gè)屬性對(duì)腳本則是完全不可見的.不過(guò),要明確的真正重要的一點(diǎn)就是,這個(gè)連接存在于實(shí)例與構(gòu)造函數(shù)的原型對(duì)象之間,而不是存在于實(shí)例與構(gòu)造函數(shù)之間.

這里引出兩個(gè)關(guān)鍵知識(shí)點(diǎn):

所有對(duì)象都有屬性__proto__指向該對(duì)象的構(gòu)造函數(shù)的原型對(duì)象,原型鏈就是靠它形成的

函數(shù)對(duì)象除了__proto__,還有屬性prototype指向該方法的原型對(duì)象,它的作用是:構(gòu)造函數(shù)實(shí)例化對(duì)象的時(shí)候,告訴構(gòu)造函數(shù)新創(chuàng)建的對(duì)象的原型是誰(shuí);

間單說(shuō)構(gòu)造函數(shù)、原型和實(shí)例的關(guān)系:每個(gè)構(gòu)造函數(shù)都有一個(gè)原型對(duì)象,原型對(duì)象都包含一個(gè)指向構(gòu)造函數(shù)的指針,而實(shí)例都包含一個(gè)指向原型對(duì)象的內(nèi)部指針.原型鏈可以讓我們做到利用原型讓一個(gè)引用類型繼承另一個(gè)引用類型的屬性和方法.

Javascript 一切皆對(duì)象(普通對(duì)象和函數(shù)對(duì)象).每個(gè)函數(shù)對(duì)象都有一個(gè)內(nèi)部鏈接到另一個(gè)對(duì)象它的原型 prototype.該原型對(duì)象有自己的原型,等等,直到達(dá)到一個(gè)以null為原型的對(duì)象.根據(jù)定義,null沒有原型,并且作為這個(gè)原型鏈 prototype chain中的最終鏈接.

例如:

function Person() {
  this.name = "mike"
}

var man = new Person;

console.log(man.__proto__ === Person.prototype); // true
//繼續(xù)深入發(fā)掘它的原型
console.log(Person.prototype.__proto__ === Object.prototype); // true

//前面說(shuō)的一切皆對(duì)象是這個(gè)意思
console.log(Function.prototype.__proto__); // Object {}
console.log(Array.prototype.__proto__); // Object {}
console.log(Number.prototype.__proto__); // Object {}


//繼續(xù)深入發(fā)掘它的最終來(lái)源是什麼
console.log(Object.prototype); // Object {}
console.log(Object.prototype.__proto__); // null

上面一步一步挖到最初的原型,有個(gè)注意的點(diǎn)容易混淆的,再?gòu)?qiáng)調(diào)一遍prototype是函數(shù)對(duì)象繼承的原型,__proto__是指向創(chuàng)建它的函數(shù)對(duì)象的原型對(duì)象prototype.只有真的弄清楚關(guān)系你才知道下面的區(qū)別

console.log(Function.prototype); // function () {}
console.log(Array.prototype); // [Symbol(Symbol.unscopables): Object]
console.log(Number.prototype); // Number {[[PrimitiveValue]]: 0}
console.log(Object.prototype); // Object {}

//下面函數(shù)對(duì)象都是通過(guò)new Function()創(chuàng)建,所以指向必定都是Function.prototype.
console.log(Function.__proto__);
console.log(Array.__proto__);
console.log(Number.__proto__);
console.log(Object.__proto__);

//細(xì)細(xì)品味這句
console.log(Function.__proto__ === Function.prototype); // true

訪問(wèn)一個(gè)對(duì)象的屬性時(shí),它先在該對(duì)象上搜尋,如果該對(duì)象沒有就搜尋該對(duì)象的原型,如果還沒有就繼續(xù)往該對(duì)象的原型的原型搜索,依此層層向上搜索,直到找到一個(gè)名字匹配的屬性或到達(dá)原型鏈的末尾(即undefined)位置.這就是上面說(shuō)的實(shí)例方法覆蓋原型對(duì)象方法認(rèn)知不準(zhǔn)確的解釋了

function Person() {
    this.name = "mike"
}

Person.prototype.age = 10;
Person.prototype.getAge = function() {
    console.log(20)
};

var man = new Person;

console.log(man.age) // 10
man.getAge() //20
console.log(man.sex) // undefined

原型對(duì)象除了__proto__之外還有一個(gè)constructor屬性,作用是返回對(duì)創(chuàng)建此對(duì)象的函數(shù)的引用.這個(gè)比較間單,直接上實(shí)例

function Person() {
  this.name = "mike"
}

var man = new Person;
console.log(man.__proto__.constructor === Person); // true
console.log(new Array().constructor); // [Function: Array]
console.log(new Number().constructor); // [Function: Number]
console.log(new Object().constructor); // [Function: Object]
console.log(new Function().constructor); // [Function: Function]

實(shí)例化對(duì)象man打印結(jié)果如下.
man.__proto__.constructor === Person

獲取檢測(cè)原型對(duì)象方法

上面獲取原型對(duì)象的方法其實(shí)不安全,

依賴瀏覽器環(huán)境暴露出來(lái)的訪問(wèn)屬性,

在實(shí)例對(duì)象變更原型對(duì)象指向的情況會(huì)失效

function Person() {
  this.name = "mike"
}

var man = new Person;
man.prototype = Object;
console.log(man.prototype); // [Function: Object]

所以我們一般通過(guò)Object.getPrototypeOf方法去獲取.

function Person() {
  this.name = "mike"
}

var man = new Person;
man.prototype = Object;
console.log(man.prototype);  // [Function: Object]
console.log(Object.getPrototypeOf(man)); // Person {}


如果是想要檢測(cè)某個(gè)對(duì)象是否構(gòu)造函數(shù)的實(shí)例,可以使用instanceof

function Person() {
  this.name = "mike"
}
var man = new Person;
console.log(man instanceof Person); // true
技巧用法

還記得上面說(shuō)的構(gòu)造函數(shù)與其他函數(shù)的唯一區(qū)別,就在于調(diào)用它們的方式不同.任何函數(shù),只要通過(guò) new 操作符來(lái)調(diào)用,那它就可以作為構(gòu)造函數(shù);而任何函數(shù),如果不通過(guò) new 操作符來(lái)調(diào)用,那它跟普通函數(shù)也不會(huì)有什麼兩樣;
用個(gè)小技巧可以讓你沒有使用new操作符也能實(shí)例化構(gòu)造函數(shù),為了區(qū)別改了點(diǎn)代碼.

function Person(name) {
  //如果是實(shí)例化對(duì)象直接賦值
  if (this instanceof Person) {
    this.name = name
  } else {
    //否則重新實(shí)例化
    return new Person(name)
  }
}
var man = new Person("mike"),
  women = Person("kitty");
console.log(man.name, women.name); // mike kitty

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

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

相關(guān)文章

  • 關(guān)於Javascript基本類型和引用類型小知識(shí)

    摘要:變量有兩種不同的數(shù)據(jù)類型基本類型,引用類型。知識(shí)一基本類型值就是簡(jiǎn)單的數(shù)據(jù)段引用類型值保存的是對(duì)象的引用,不是實(shí)際的對(duì)象。 ECMAScirpt 變量有兩種不同的數(shù)據(jù)類型:基本類型,引用類型。 基本的數(shù)據(jù)類型有:undefined,boolean,number,string,null. 基本類型的訪問(wèn)是按值訪問(wèn)的,就是說(shuō)你可以操作保存在變量中的實(shí)際的值。JavaScript中除了上面的...

    iKcamp 評(píng)論0 收藏0
  • 《前端竹節(jié)》(3)【原型對(duì)象】

    摘要:從原型對(duì)象指向構(gòu)造函數(shù)畫一條帶箭頭的線。線上標(biāo)注,表示該原型對(duì)象的構(gòu)造函數(shù)等于。但除此之外,若構(gòu)造函數(shù)所指的顯示原型對(duì)象存在于的原型鏈上,結(jié)果也都會(huì)為。執(zhí)行構(gòu)造函數(shù),并將指針綁定到新創(chuàng)建的對(duì)象上。 做前端開發(fā)有段時(shí)間了,遇到過(guò)很多坎,若是要排出個(gè)先后順序,那么JavaScript的原型與對(duì)象絕對(duì)逃不出TOP3。 如果說(shuō)前端是海,JavaScript就是海里的水 一直以來(lái)都想寫篇文章梳理...

    lentrue 評(píng)論0 收藏0
  • 原型原型理解

    原型與原型鏈理解 1. 什么是原型 JavaScript是一種簡(jiǎn)易的腳本語(yǔ)言,其是由對(duì)象構(gòu)成。每一個(gè)JavaScript對(duì)象(除null外)都和另一個(gè)對(duì)象相關(guān)聯(lián),另一個(gè)對(duì)象就是原型。也就是說(shuō),任何一個(gè)對(duì)象都有原型這個(gè)屬性。 隱式原型(_proto_):上面說(shuō)的這個(gè)原型是JavaScript中的內(nèi)置屬性[[prototype]],此屬性繼承自object對(duì)象,在腳本中沒有標(biāo)準(zhǔn)的方式訪問(wèn)[[pro...

    YJNldm 評(píng)論0 收藏0
  • js對(duì)象詳解(JavaScript對(duì)象深度剖析,深度理解js對(duì)象)

    摘要:對(duì)象詳解對(duì)象深度剖析,深度理解對(duì)象這算是醞釀很久的一篇文章了。用空構(gòu)造函數(shù)設(shè)置類名每個(gè)對(duì)象都共享相同屬性每個(gè)對(duì)象共享一個(gè)方法版本,省內(nèi)存。 js對(duì)象詳解(JavaScript對(duì)象深度剖析,深度理解js對(duì)象) 這算是醞釀很久的一篇文章了。 JavaScript作為一個(gè)基于對(duì)象(沒有類的概念)的語(yǔ)言,從入門到精通到放棄一直會(huì)被對(duì)象這個(gè)問(wèn)題圍繞。 平時(shí)發(fā)的文章基本都是開發(fā)中遇到的問(wèn)題和對(duì)...

    CatalpaFlat 評(píng)論0 收藏0
  • 面向?qū)ο蟮男【啪?/b>

    摘要:由構(gòu)造函數(shù)返回的對(duì)象就是表達(dá)式的結(jié)果。如果構(gòu)造函數(shù)沒有顯式返回一個(gè)對(duì)象,則使用步驟創(chuàng)建的對(duì)象。運(yùn)算符返回一個(gè)布爾值,表示對(duì)象是否為某個(gè)構(gòu)造函數(shù)的實(shí)例。 面向?qū)ο?本人能力有限,有誤請(qǐng)斧正 本文旨在復(fù)習(xí)面向?qū)ο?不包含es6) 本文學(xué)習(xí)思維 創(chuàng)建對(duì)象的方式,獲取對(duì)象屬性 構(gòu)造函數(shù),構(gòu)造函數(shù)的new 做了什么 原型與原型對(duì)象 原型鏈 繼承(借用構(gòu)造繼承、原型繼承、組合繼承、寄生組合繼承)...

    時(shí)飛 評(píng)論0 收藏0

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

0條評(píng)論

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