亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專欄INFORMATION COLUMN

關於Javascript中的new運算符,構造函數與原型鏈一些理解

cikenerd / 1992人閱讀

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

前言

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

構造函數
new constructor(arguments): 

創(chuàng)建一個用護定義的對象類型的實例或具有構造函數的內置對象類型之一

new命令: 執(zhí)行構造函數返回一個實例對象

構造函數(constructor): 一個指定對象實例的類型的函數

傳慘(arguments): 一個用來被構造函數調用的慘數列表

注意點幾個:

默認構造函數首字母大寫區(qū)分函數類型

在不傳遞任何慘數的情況new constructor可以省略括號

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

使用構造函數的主要問題,就是每個方法都要在每個實例上重新創(chuàng)建一遍

new存在的意義在于它實現了javascript中的繼承,而不僅僅是實例化了一個對象

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

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

當代碼執(zhí)行時會經過幾個步驟:

以下是我基于JS高程3總結的:

一個新的空對象被創(chuàng)建

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

執(zhí)行構造函數中的代碼(為這個新對象添加屬性)等初始化工作

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

以下是原版:

創(chuàng)建一個新對象

將構造函數的作用域賦給新對象(因此 this 就指向了這個新對象)

執(zhí)行構造函數中的代碼(為這個新對象添加屬性)

返回新對象.

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

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

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

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

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

3、若返回值是引用類型,則實際返回值為這個引用類型.

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

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

初學者特別應該注意的是他們之間是不同的,所謂的構造函數是創(chuàng)建一個用戶定義的對象類型的實例或具有構造函數的內置對象類型之一

正常來說構造函數不需要有返回值的,可以認為構造函數和普通函數的最大差別就是:構造函數中沒有return語句,普通函數可以有return語句;構造函數中會使用this關鍵字定義成員變量和成員方法,普通的函數不會使用this關鍵字定義成員變量和方法.
像第二種情況即使返回基本類型也會被忽略掉,只有選擇返回一個普通對象才會取代整個new出來的結果

原型對象(prototype)

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

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

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

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

有一種情況是對象實例自身已經賦有同名屬性方法會覆蓋 prototype 上的屬性方法.這個認知是不準確的,下面的原型鏈會講到這部分.

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

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

man.getAge() // 81

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

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

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

man.getAge() // 81
原型鏈

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

理解原型對象(關鍵詞 prototype, constructor, __proto__)
無論什麼時候,只要創(chuàng)建了一個新函數,就會根據一組特定的規(guī)則為該函數創(chuàng)建一個 prototype 屬性,這個屬性指向函數的原型對象.

在默認情況下,所有原型對象都會自動獲得一個 constructor(構造函數)屬性,這個屬性包含一個指向 prototype 屬性所在函數的指針.

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

當調用構造函數創(chuàng)建一個新實例后,該實例的內部將包含一個指針(內部屬性),指向構造函數的原型對象.

ECMA-262 第 5 版中管這個指針叫 [[Prototype]] .雖然在腳本中沒有標準的方式訪問 [[Prototype]] ,但 Firefox、Safari 和 Chrome 在每個對象上都支持一個屬性__proto__ ;而在其他實現中,這個屬性對腳本則是完全不可見的.不過,要明確的真正重要的一點就是,這個連接存在于實例與構造函數的原型對象之間,而不是存在于實例與構造函數之間.

這里引出兩個關鍵知識點:

所有對象都有屬性__proto__指向該對象的構造函數的原型對象,原型鏈就是靠它形成的

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

間單說構造函數、原型和實例的關系:每個構造函數都有一個原型對象,原型對象都包含一個指向構造函數的指針,而實例都包含一個指向原型對象的內部指針.原型鏈可以讓我們做到利用原型讓一個引用類型繼承另一個引用類型的屬性和方法.

Javascript 一切皆對象(普通對象和函數對象).每個函數對象都有一個內部鏈接到另一個對象它的原型 prototype.該原型對象有自己的原型,等等,直到達到一個以null為原型的對象.根據定義,null沒有原型,并且作為這個原型鏈 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

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


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

上面一步一步挖到最初的原型,有個注意的點容易混淆的,再強調一遍prototype是函數對象繼承的原型,__proto__是指向創(chuàng)建它的函數對象的原型對象prototype.只有真的弄清楚關系你才知道下面的區(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 {}

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

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

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

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

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

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]

實例化對象man打印結果如下.
man.__proto__.constructor === Person

獲取檢測原型對象方法

上面獲取原型對象的方法其實不安全,

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

在實例對象變更原型對象指向的情況會失效

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

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

所以我們一般通過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 {}


如果是想要檢測某個對象是否構造函數的實例,可以使用instanceof

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

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

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

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

轉載請注明本文地址:http://www.ezyhdfw.cn/yun/106174.html

相關文章

  • 關於Javascript基本類型和引用類型小知識

    摘要:變量有兩種不同的數據類型基本類型,引用類型。知識一基本類型值就是簡單的數據段引用類型值保存的是對象的引用,不是實際的對象。 ECMAScirpt 變量有兩種不同的數據類型:基本類型,引用類型。 基本的數據類型有:undefined,boolean,number,string,null. 基本類型的訪問是按值訪問的,就是說你可以操作保存在變量中的實際的值。JavaScript中除了上面的...

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

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

    lentrue 評論0 收藏0
  • 原型原型理解

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

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

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

    CatalpaFlat 評論0 收藏0
  • 面向對象的小九九

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

    時飛 評論0 收藏0

發(fā)表評論

0條評論

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