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

資訊專欄INFORMATION COLUMN

夯實(shí)基礎(chǔ)-數(shù)據(jù)類型與繼承

codecraft / 1906人閱讀

摘要:通過上面的圖我想應(yīng)該一目了然了,基本數(shù)據(jù)類型都是存在棧內(nèi)存中的,復(fù)雜對(duì)象則是存在堆內(nèi)存中,棧內(nèi)存變量保存的是其內(nèi)存地址。等同于如果使用則規(guī)則相對(duì)簡(jiǎn)單值為基本數(shù)據(jù)類型數(shù)值轉(zhuǎn)為相應(yīng)的字符串。

數(shù)據(jù)類型是基礎(chǔ)中的基礎(chǔ),大家天天遇到,我們這次來討論深一點(diǎn),將我們認(rèn)為理所當(dāng)然的事情背后的原理發(fā)掘;繼承也是前端基礎(chǔ)一個(gè)大考點(diǎn),看看繼承的原理與使用場(chǎng)景。

本文討論以下幾個(gè)點(diǎn):

JavaScript數(shù)據(jù)類型

不同數(shù)據(jù)類型對(duì)應(yīng)的數(shù)據(jù)結(jié)構(gòu)

數(shù)據(jù)類型轉(zhuǎn)換

數(shù)組與對(duì)象的api表

new關(guān)鍵字背后干了些什么

原型與原型屬性與構(gòu)造函數(shù)區(qū)別于聯(lián)系

實(shí)例化,混入,繼承,多態(tài)是什么意思

數(shù)據(jù)類型

最新的 ECMAScript 標(biāo)準(zhǔn)定義了 7 種數(shù)據(jù)類型:

6 種原始類型:

Boolean

Null

Undefined

Number

String

Symbol (ECMAScript 6 新定義)

和 Object

這個(gè)分類我們應(yīng)該是相當(dāng)熟悉了,當(dāng)時(shí)這是按照什么標(biāo)準(zhǔn)分類的。

數(shù)據(jù)類型對(duì)應(yīng)的數(shù)據(jù)結(jié)構(gòu)

事實(shí)上上面的分類標(biāo)準(zhǔn)是按照不同數(shù)據(jù)在計(jì)算機(jī)內(nèi)存中的結(jié)構(gòu)分類的。我們都知道JavaScript中的變量運(yùn)行的時(shí)候是存在內(nèi)存中的,如果接觸過java的人應(yīng)該知道,內(nèi)存中也分為棧內(nèi)存和堆內(nèi)存。

棧(stack)

基本類型Undefined、Null、Boolean、Number 和String。這些類型在內(nèi)存中分別占有固定大小的空間,他們的值保存在棧內(nèi)存,他們的值保存在棧內(nèi)存,我們通過按值來訪問的。

var a = "1";
var b = "1";
a === b;

上述代碼執(zhí)行時(shí)候,可以理解為:

聲明變量a,b,為a,b分配一個(gè)棧內(nèi)存空間。(變量提升)

要賦值a,將a的字面量"1"作為值存儲(chǔ)到a在棧內(nèi)存的值中。

要賦值b,同樣將"1"作為棧內(nèi)存的值存儲(chǔ)。

這種簡(jiǎn)單數(shù)據(jù)類型,都是在棧內(nèi)存中保存其值。

JavaScript中的原始值(基本數(shù)據(jù)類型)都可預(yù)知其最大最小內(nèi)存大小,所以創(chuàng)建的時(shí)候直接分配對(duì)應(yīng)的內(nèi)存空間。

堆(heap)

復(fù)雜的數(shù)據(jù)類型,如object,array,function等,無法提前預(yù)知其要占用多少內(nèi)存空間,所以這個(gè)數(shù)據(jù)類型被放入了堆內(nèi)存中,同時(shí)在棧內(nèi)存中保存其堆內(nèi)存的地址,訪問這些變量的時(shí)候,在棧內(nèi)存中獲取到其內(nèi)存地址,然后訪問到該對(duì)象,這種方式叫按引用訪問。

var a = "hello world";
var b = 123;
var c = null;
var d = undefined;
var e = {};
var f = function(){console.log(1);};
var g = [1,2,a];

其在內(nèi)存中的簡(jiǎn)易模型如下:

上面這個(gè)圖并不是完全準(zhǔn)確的,這里只是簡(jiǎn)單形容一下不同數(shù)據(jù)類型變量的存儲(chǔ)關(guān)系,偏底層的知識(shí)真的需要多帶帶開一篇來講了。

通過上面的圖我想應(yīng)該一目了然了,基本數(shù)據(jù)類型都是存在棧內(nèi)存中的,復(fù)雜對(duì)象則是存在堆內(nèi)存中,棧內(nèi)存變量保存的是其內(nèi)存地址。這也應(yīng)該想到了我們經(jīng)常遇到的問題:對(duì)象之間賦值,賦值的是真正的內(nèi)存地址;對(duì)象相互比較===,比較的是內(nèi)存地址。

變量賦值

JavaScript 引用指向的是值。如果一個(gè)值有 10 個(gè)引用,這些引用指向的都是同一個(gè)值,它們相互之間沒有引用 / 指向關(guān)系。

JavaScript 對(duì)值和引用的賦值 / 傳遞在語法上沒有區(qū)別,完全根據(jù)值的類型來決定:

簡(jiǎn)單數(shù)據(jù)類型總是通過值復(fù)制的方式來賦值 / 傳遞。

復(fù)雜數(shù)據(jù)類型則總是通過引用復(fù)制的方式來賦值 / 傳遞。

包裝類和類型轉(zhuǎn)換 內(nèi)置對(duì)象

JavaScript內(nèi)置了一些對(duì)象,這些對(duì)象可以在全局任意地方調(diào)用,并且有各自的屬性和方法。MDN上羅列了全部,這里只挑一部分對(duì)象說明:

Object

Array

Function

String

Number

Boolean

Math

Date

RegExp

ok通過上面的幾個(gè)內(nèi)置對(duì)象就會(huì)發(fā)現(xiàn)一些問題:一些基本數(shù)據(jù)類型(String,Number,Boolean)有對(duì)應(yīng)的內(nèi)置對(duì)象,但是其他的一些(Null, Undefined)就沒有,復(fù)雜數(shù)據(jù)類型則都有,這是為什么。

包裝類
var a = "hello world";
a[1]; // "e"
a.length; // 11
a.toString(); // hello world
a.valueOf(); // hello world
a.split(" "); // ["hello", "world"]

有沒有想過,變量a命名是個(gè)基本類型,不是對(duì)象,為什么會(huì)有這么多屬性和方法。因?yàn)檫@些內(nèi)置的屬性和方法都在內(nèi)置對(duì)象String上。

事實(shí)上當(dāng)你調(diào)用這些基本數(shù)據(jù)類型上屬性和方法時(shí)候,引擎會(huì)自動(dòng)尋找其是否有對(duì)應(yīng)的包裝類,有的話生成一個(gè)包裝類的實(shí)例供你使用(使用之后銷毀),否則報(bào)錯(cuò)。

var a = "hello world";
a.customAttribute // undefined
String.prototype.customAttribute = "custom";
var b = "hello world";
b.customAttribute // custom

我們現(xiàn)在想要訪問屬性customAttribute,這個(gè)屬性沒有在內(nèi)置對(duì)象上,所以獲取到的值是undefined;我們向內(nèi)置對(duì)象的原型鏈上添加該屬性,之后所有的string上都可以獲取到該值。

類型轉(zhuǎn)換

JavaScript中的類型轉(zhuǎn)換也是個(gè)大坑,不少面試都會(huì)問到。JavaScript 是一種動(dòng)態(tài)類型語言,變量沒有類型限制,可以隨時(shí)賦予任意值。

顯示轉(zhuǎn)換

直接調(diào)用對(duì)應(yīng)的包裝類進(jìn)行轉(zhuǎn)換。具體可分成三種情況:

// 數(shù)值:轉(zhuǎn)換后還是原來的值
Number(324) // 324

// 字符串:如果可以被解析為數(shù)值,則轉(zhuǎn)換為相應(yīng)的數(shù)值
Number("324") // 324

// 字符串:如果不可以被解析為數(shù)值,返回 NaN
Number("324abc") // NaN

// 空字符串轉(zhuǎn)為0
Number("") // 0

// 布爾值:true 轉(zhuǎn)成 1,false 轉(zhuǎn)成 0
Number(true) // 1
Number(false) // 0

// undefined:轉(zhuǎn)成 NaN
Number(undefined) // NaN

// null:轉(zhuǎn)成0
Number(null) // 0

使用Number包裝類來進(jìn)行類型轉(zhuǎn)換,隱藏的邏輯:

調(diào)用對(duì)象自身的valueOf方法。如果返回原始類型的值,則直接對(duì)該值使用Number函數(shù),不再進(jìn)行后續(xù)步驟。

如果valueOf方法返回的還是對(duì)象,則改為調(diào)用對(duì)象自身的toString方法。如果toString方法返回原始類型的值,則對(duì)該值使用Number函數(shù),不再進(jìn)行后續(xù)步驟。

如果toString方法返回的是對(duì)象,就報(bào)錯(cuò)。

var obj = {x: 1};
Number(obj) // NaN

// 等同于
if (typeof obj.valueOf() === "object") {
  Number(obj.toString());
} else {
  Number(obj.valueOf());
}

var obj1 = {
  valueOf: function () {
    return {};
  },
  toString: function () {
    return {};
  }
};

Number(obj1)
// TypeError: Cannot convert object to primitive value

Number({
  valueOf: function () {
    return 2;
  }
})
// 2

Number({
  toString: function () {
    return 3;
  }
})
// 3

Number({
  valueOf: function () {
    return 2;
  },
  toString: function () {
    return 3;
  }
})
// 2

如果使用String則規(guī)則相對(duì)簡(jiǎn)單:

值為基本數(shù)據(jù)類型

數(shù)值:轉(zhuǎn)為相應(yīng)的字符串。

字符串:轉(zhuǎn)換后還是原來的值。

布爾值true轉(zhuǎn)為字符串"true",false轉(zhuǎn)為字符串"false"

undefined:轉(zhuǎn)為字符串"undefined"。

null:轉(zhuǎn)為字符串"null"。

值為對(duì)象

先調(diào)用對(duì)象自身的toString方法。如果返回原始類型的值,則對(duì)該值使用String函數(shù),不再進(jìn)行以下步驟。

如果toString方法返回的是對(duì)象,再調(diào)用原對(duì)象的valueOf方法。如果valueOf方法返回原始類型的值,則對(duì)該值使用String函數(shù),不再進(jìn)行以下步驟。

如果valueOf方法返回的是對(duì)象,就報(bào)錯(cuò)。

Boolean規(guī)則更簡(jiǎn)單:除了五個(gè)值(undefined,null,(+/-)0,NaN,‘’)的轉(zhuǎn)換結(jié)果為false,其他的值全部為true

隱式轉(zhuǎn)換

隱式轉(zhuǎn)換也分三種情況:

轉(zhuǎn)布爾值

JavaScript 遇到預(yù)期為布爾值的地方(比如if語句的條件部分),就會(huì)將非布爾值的參數(shù)自動(dòng)轉(zhuǎn)換為布值。系統(tǒng)內(nèi)部會(huì)自動(dòng)調(diào)用Boolean函數(shù)。

所以跟上面一樣,因此除了五個(gè)值(undefined,null,(+/-)0,NaN,‘’),其他都是自動(dòng)轉(zhuǎn)為true

轉(zhuǎn)字符串

JavaScript 遇到預(yù)期為字符串的地方,就會(huì)將非字符串的值自動(dòng)轉(zhuǎn)為字符串。具體規(guī)則是,先將復(fù)合類型的值轉(zhuǎn)為原始類型的值,再將原始類型的值轉(zhuǎn)為字符串。

字符串的自動(dòng)轉(zhuǎn)換,主要發(fā)生在字符串的加法運(yùn)算時(shí)。當(dāng)一個(gè)值為字符串,另一個(gè)值為非字符串,則后者轉(zhuǎn)為字符串。

"5" + 1 // "51"
"5" + true // "5true"
"5" + false // "5false"
"5" + {} // "5[object Object]"
"5" + [] // "5"
"5" + function (){} // "5function (){}"
"5" + undefined // "5undefined"
"5" + null // "5null"

轉(zhuǎn)數(shù)值

JavaScript 遇到預(yù)期為數(shù)值的地方,就會(huì)將參數(shù)值自動(dòng)轉(zhuǎn)換為數(shù)值。系統(tǒng)內(nèi)部會(huì)自動(dòng)調(diào)用Number函數(shù)。

除了加法運(yùn)算符(+)有可能把運(yùn)算子轉(zhuǎn)為字符串,其他運(yùn)算符都會(huì)把運(yùn)算子自動(dòng)轉(zhuǎn)成數(shù)值。

"5" - "2" // 3
"5" * "2" // 10
true - 1  // 0
false - 1 // -1
"1" - 1   // 0
"5" * []    // 0
false / "5" // 0
"abc" - 1   // NaN
null + 1 // 1
undefined + 1 // NaN

具體參考阮一峰老師:JavaScript類型轉(zhuǎn)換

數(shù)組和對(duì)象

這三個(gè)復(fù)雜對(duì)象我們太熟悉不過了,每天都在打交道。但是實(shí)際上我們也并不是完全掌握。

數(shù)組(Array)

數(shù)組方法很多,我們可以分類來整理記憶。

有哪些方法返回的是新數(shù)組

concat

slice

filter

map

forEach

遍歷數(shù)組方法有幾種,區(qū)別在于什么

常見的有:

map:返回新數(shù)組,數(shù)組的每一項(xiàng)都是測(cè)試函數(shù)的返回值。

forEach:不返回任何值,只是單純遍歷一遍數(shù)組。

every:遍歷數(shù)組所有元素,直到測(cè)試函數(shù)返回第一個(gè)false停止。

some:遍歷數(shù)組所有元素,直到測(cè)試函數(shù)返回第一個(gè)true停止。

for循環(huán):寫起來最麻煩,但是性能最好。

filter方法傳入函數(shù)的參數(shù)有幾個(gè),都是什么含義

不只是filter方法,類似這種第一個(gè)參數(shù)為callback的方法如:some,every,forEach,map,find,findIndex的方法callback參數(shù)都一樣:currentValue,Index,array。
github上參照了MDN整理了一份完整的文檔,用于自己的查缺補(bǔ)漏。

對(duì)象(Object)

創(chuàng)建對(duì)象的方法有幾種

字面量方式:

var person={
    name:"SF",
    age:25
    say:function(){
       alert(this.name+"今年"+this.age);
    }
};
person.say();

利用Object對(duì)象創(chuàng)建實(shí)例

var my = new Object();
my.name = "SF"; //JavaScript的發(fā)明者
my.age = 25;
my.say = function() { 
  alert("我是"+this.name+"今年"+my.age);
}
my.say();

var obj = Object.create(null);
obj.name = "SF";

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

function Person(name,age) { 
  this.name = name; 
  this.age = age; 
  this.say = function() { 
      alert("我叫" + this.name + ",今年" + this.age + "歲); 
  }
}
var my = new Person("SF",25); //實(shí)例化、創(chuàng)建對(duì)象
my.say(); //調(diào)用say()方法

原型模式

function Person() {
}
Person.prototype.name = "aus";
Person.prototype.job = "fe"
Person.prototype.sayName = function() {
  console.log(this.name)
}
var person1 = new Person();

組合構(gòu)造函數(shù)和原型

function Person( name, age, job ) {
    this.name = name;
    this.age = age;
    this.job = job;
    this.friends = ["Shelby","Court"];
}

Person.prototype = {
    constructor: Person,
    sayName: function(){
        alert(this.name);
    }
}

var person1 = new Person("Nicholas", 29, "software Engineer");
var person2 = new Person("Greg", 27, "Doctor");

person1.friends.push("Van");

alert(person1.friends); //"Shelby,Court,Van"
alert(person2.friends); //"Shelby,Court"
alert(person1.friends === person2.friends); //false
alert(person1.sayName === person2.sayName); //true

對(duì)象的擴(kuò)展密封和凍結(jié)有什么區(qū)別

擴(kuò)展特性

Object.isExtensible 方法

Object.preventExtensions 方法

密封特性

Object.isSealed 方法

Object.seal 方法

凍結(jié)特性

Object.isFrozen 方法

Object.freeze 方法

淺凍結(jié)深凍結(jié)

簡(jiǎn)單說就是對(duì)象有可擴(kuò)展性(可以隨意添加屬性),限制對(duì)象的可擴(kuò)展性(Object.preventExtensions)之后,對(duì)象不可添加新屬性(但是現(xiàn)有屬性可以修改和刪除)。

密封對(duì)象(seal)指的是對(duì)象的屬性不可增加或者刪除,并且屬性配置不可修改(屬性值可修改)。

凍結(jié)對(duì)象(freeze)則更加嚴(yán)格,不可增加或者刪除屬性,并且屬性完全不可修改。

這里不做過多介紹,詳細(xì)可以看這里。

怎樣快速實(shí)現(xiàn)淺拷貝以及深拷貝

Object.assign是常見的淺拷貝方法,怎樣自己實(shí)現(xiàn)。

// 利用原生api
function shallowClone(obj) {
  return Object.create(
      Object.getPrototypeOf(obj), 
      Object.getOwnPropertyDescriptors(obj) 
  );
}

// 屬性淺拷貝
function shallowCopy(copyObj) {
  var obj = {};
  for ( var i in copyObj) {
    obj[i] = copyObj[i];
  }
  return obj;
}

深拷貝之前整理過:github。

對(duì)象的方法參照MDN整理了一份,github。

原型鏈

這節(jié)算是給繼承鋪墊基礎(chǔ)知識(shí)了,js里最出名的原型和原型鏈,面試必考,日常開發(fā)也特別常見。

prototype

prototype中文譯為"原型",大部分Object和Function都有prototype。個(gè)人覺得原型是一個(gè)特殊的普通對(duì)象,對(duì)象里面的屬性和方法都用于指定的用途:共享。我們可以按照自己的意愿去修改原型,并且重新被共享。

當(dāng)創(chuàng)建函數(shù)的時(shí)候,每一個(gè)函數(shù)都會(huì)自動(dòng)有一個(gè)prototype屬性,這個(gè)屬性的值是空對(duì)象(空對(duì)象不是空)。

一旦你把這個(gè)函數(shù)當(dāng)成構(gòu)造函數(shù)調(diào)用(通過new調(diào)用)JS會(huì)創(chuàng)建構(gòu)造函數(shù)的實(shí)例,實(shí)例是不具有原型的。

function A (){};
A.prototype // {}

var a = new A();
a.prototype // undefined
proto

中文翻譯過來叫"原型屬性",這是一個(gè)隱式屬性,不可被枚舉,但是他的用途至關(guān)重要。每個(gè)對(duì)象創(chuàng)建的時(shí)候,都會(huì)有一個(gè)隱式的屬性__proto__,該屬性的值是其對(duì)應(yīng)的原型(其實(shí)就是說明 該對(duì)象的來源)。

function A (){};
A.__proto__ === Function.prototype; // true

var b = {};
b.__proto__ === Object.prototype; // true

var c = [];
c.__proto__ === Array.prototype; // true

可以確定的是,__proto__指向的是其構(gòu)造函數(shù)的原型。

contructor

構(gòu)造函數(shù)實(shí)例都擁有指向其構(gòu)造函數(shù)的constructor屬性。constructor屬性的值是一個(gè)函數(shù)對(duì)象 為了將實(shí)例的構(gòu)造器的原型對(duì)象暴露出來。

function A(){};
A.constructor === Function // true

var a = new A();
a.construtor === A // true

var obj = {};
obj.constructor === Object // true

可以確定的是,constructor屬性指向其構(gòu)造函數(shù)。

關(guān)系

上面三者的關(guān)系可以用下圖表示:

這里就不得不提一句:使用new關(guān)鍵字實(shí)例化對(duì)象,內(nèi)在過程到底發(fā)生了什么。

我們可以理解為將new關(guān)鍵字實(shí)例化對(duì)象拆成兩步:

function A(){};

function create (base) {
    var obj  = {};
    obj.__proto__ = base.prototype;
    base.call(obj);
    return obj;
}

var a = create(A);

a instanceof A // true
原型鏈

上面三個(gè)角色到期了之后,就到了另一個(gè)重點(diǎn):原型鏈。

var a = Object.create(null);
a.a = 1;
var b = Object.create(a);
b.b = 2;
var c = Object.create(b);
c.c = 3;

c.a // 1
c.b // 2
c.c // 3

a.d = 4;
c.d;

c.a = 0;
c.a; // 0

上面這個(gè)例子用到了Object.create函數(shù)創(chuàng)建了一個(gè)原型為空的對(duì)象a??梢钥吹絚并沒有a,b屬性,但是卻可以讀出該值來,這就是原型鏈。

當(dāng)訪問一個(gè)對(duì)象的屬性(方法)的時(shí)候,如果對(duì)象自身沒有該屬性(方法),就會(huì)去該對(duì)象的__proto__上尋找,如果__proto__上也沒有,就去__proto__.__proto__上尋找,以此類推,直到找到一個(gè)值返回;若沒有則返回undefined。這種按照對(duì)象原型屬性尋找形成一個(gè)類似鏈狀的結(jié)構(gòu),叫做原型鏈。

畫個(gè)圖表示:

上圖中的__proto__紅線可以理解為原型鏈。

這里要注意的是,對(duì)象的原型屬性,保存的是對(duì)象的內(nèi)存地址引用,需要讀取原型屬性的時(shí)候會(huì)找到該對(duì)象當(dāng)時(shí)的狀態(tài),所以更改原型鏈上原型屬性對(duì)象,會(huì)對(duì)該條原型鏈上的其他對(duì)象造成影響。

繼承

ok經(jīng)過這么多鋪墊終于來到了繼承,繼承是面向?qū)ο罄锩孀钪匾母拍钪?。我們先來把相關(guān)概念介紹,再來看動(dòng)手實(shí)現(xiàn)。

不管是實(shí)例,混入或者繼承,他們的誕生都是為了解決同一個(gè)問題:代碼復(fù)用。只不過實(shí)現(xiàn)方式不同。

實(shí)例

這個(gè)是我們?nèi)粘i_發(fā)中最常用的一種。

var date = new Date();

var instanceLightBox = new LightBox();

實(shí)例化一個(gè)對(duì)象可以理解為調(diào)用類的構(gòu)造函數(shù),返回一個(gè)擁有類所有屬性和方法的對(duì)象。

這樣說可能也不準(zhǔn)確,我們以var a = new A();為例,實(shí)例化一個(gè)對(duì)象有幾個(gè)特點(diǎn):

a是一個(gè)object;

a的構(gòu)造函數(shù)是A;

A構(gòu)造函數(shù)中的非私有屬性會(huì)被a獲取到;

A的原型是a的原型屬性;

function A () {
    this.a = 1;
};

A.prototype.getA = function(){
    return this.a;
}

var a = new A();

a.a; // 1
a.getA(); // 1 

事實(shí)上我們?cè)谏厦嬉呀?jīng)講解了調(diào)用new關(guān)鍵字發(fā)生了什么,這里原理不多講。為什么要用實(shí)例化類:我們可以吧構(gòu)造函數(shù)當(dāng)做一個(gè)工廠,工廠產(chǎn)出了定制化模板(構(gòu)造函數(shù))和標(biāo)準(zhǔn)模板(構(gòu)造函數(shù)的原型)的產(chǎn)品;我們可以通過多次實(shí)例化一個(gè)類,產(chǎn)出多個(gè)一樣的產(chǎn)品,從而實(shí)現(xiàn)了代碼復(fù)用。

混入(mixin)

混入更像是一個(gè)加工廠,對(duì)已有的對(duì)象進(jìn)行添加新屬性的操作。

function A (){
    this.a = 1;
};

// 一個(gè)非常簡(jiǎn)單的mixin例子
function mixin(sourceObj, targetObj){
    for (var key in sourceObj) {
        // 只會(huì)在不存在的情況下復(fù)制
        if (!(key in targetObj)) {
            targetObj[key] = sourceObj[key];
        }
    }
}

var a = new A();
var b = {b:2};
mixin(b, a);
a.b; // 2

這個(gè)例子可以看到,targetObj混入了sourceObj的特有屬性,如果屬性是方法或者對(duì)象的話,targetObj保存的知識(shí)對(duì)象的引用,而不是自己獨(dú)有的屬性,這樣sourceObject更改targetObj也會(huì)跟著更改。

繼承(extend)

繼承里面有兩個(gè)角色,父類和子類。繼承理解為得到父類所有的屬性,并且可以重寫這些屬性。同樣是獲得一個(gè)function全部的屬性和方法,我認(rèn)為實(shí)例和繼承的最大區(qū)別在于實(shí)例是構(gòu)造函數(shù)實(shí)例對(duì)象,繼承是類繼承類,數(shù)據(jù)類型有明顯區(qū)別。

我們先來看看ES6中的繼承:

class Parent {
    constructor (props) {
        const {name, phone} = props;
        this.name = name;
        this.phone = phone;
    }
       getInfo(){
        return this.name + ":" + this.phone;
    }
}

class Child extends Parent {
    constructor(props){
        super(props);
        const {gender} = props;
        this.gender = gender;
    }
    getNewInfo(){
        return this.name + ":" + this.gender + ":" + this.phone;
    }    
}

var childIns = new Child({
    name: "aus",
    gender: "male",
    phone: "1888888888"
});

先不討論繼承是如何實(shí)現(xiàn)的,先來看看繼承的結(jié)果。ES6中的繼承,Child類拿到了Parent類的構(gòu)造器里的非屬性和原型上的所有屬性,并且可以擴(kuò)展自己的私有屬性和原型屬性。但是父類和子類仍然公用父類的原型。

繼承有三個(gè)特點(diǎn):

子類擁有父類非私有的屬性和方法。

子類可以擁有自己屬性和方法,即子類可以對(duì)父類進(jìn)行擴(kuò)展。

子類可以用自己的方式實(shí)現(xiàn)父類的方法。

多態(tài)

這里多態(tài)不詳細(xì)介紹,我們來了解概念與實(shí)例。

多態(tài):同一操作作用于不同的對(duì)象,可以有不同的解釋,產(chǎn)生不同的執(zhí)行結(jié)果。

舉個(gè)例子,父類原型上有個(gè)方法a,子類原型上有個(gè)同名方法a,這樣在子類實(shí)例上調(diào)用a方法必然是子類定義的a,但是我如果想用父類上的a怎么辦。

class Parent {
    constructor (props) {
        const {name, phone} = props;
        this.name = name;
        this.phone = phone;
    }
       getInfo(){
        return this.name + ":" + this.phone;
    }
}

class Child extends Parent {
    constructor(props){
        super(props);
        const {gender} = props;
        this.gender = gender;
    }
    getInfo(from){
        // 全完自定義
        if("child" === from){
            return this.getNewInfo();
        } else {
            return super.getInfo();   
        }
    }
    getNewInfo(){
        return this.name + ":" + this.gender + ":" + this.phone;
    }    
}

var childIns = new Child({
    name: "aus",
    gender: "male",
    phone: "1888888888"
});
多態(tài)是一個(gè)非常廣泛的話題,我們現(xiàn)在所說的“相對(duì)”只是多態(tài)的一個(gè)方面:任何方法都可以引用繼承層次中高層的方法(無論高層的方法名和當(dāng)前方法名是否相同)。之所以說“相對(duì)”是因?yàn)槲覀儾⒉粫?huì)定義想要訪問的絕對(duì)繼承層次(或者說類),而是使用相對(duì)引用“查找上一層”。
繼承實(shí)現(xiàn)

一道非常常見的面試題,有多種方法,分成兩個(gè)思路,篇幅有限,不過多介紹,詳細(xì)的文檔在github上,或者自行g(shù)oogle。

參考

《JavaScript權(quán)威指南》

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

《你所不知道的JavaScript》

JavaScript變量——棧內(nèi)存or堆內(nèi)存

內(nèi)存管理

數(shù)據(jù)類型轉(zhuǎn)換

面向?qū)ο缶幊倘筇匦?-----封裝、繼承、多態(tài)

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

轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/94644.html

相關(guān)文章

  • 夯實(shí)基礎(chǔ)系列一:Java 基礎(chǔ)總結(jié)

    摘要:可實(shí)現(xiàn)單例模式代碼塊初始化靜態(tài)變量,只被執(zhí)行一次內(nèi)部類不能與外部類重名,只能訪問外部類靜態(tài)數(shù)據(jù)包括私有多分支選擇整型或字符類型變量或整數(shù)表達(dá)式開始支持。 前言 大學(xué)期間接觸 Java 的時(shí)間也不短了,不論學(xué)習(xí)還是實(shí)習(xí),都讓我發(fā)覺基礎(chǔ)的重要性?;ヂ?lián)網(wǎng)發(fā)展太快了,各種框架各種技術(shù)更新迭代的速度非???,可能你剛好掌握了一門技術(shù)的應(yīng)用,它卻已經(jīng)走在淘汰的邊緣了。 而學(xué)習(xí)新技術(shù)總要付出一定的時(shí)間...

    greatwhole 評(píng)論0 收藏0
  • 夯實(shí)基礎(chǔ)-java equals使用,和 == 的區(qū)別

    摘要:在這些類當(dāng)中有其自身的實(shí)現(xiàn)一般都是用來比較對(duì)象的成員變量值是否相同,而不再是比較類在堆內(nèi)存中的存放地址了。舉例說明結(jié)果說明中有其自身的實(shí)現(xiàn),屬于內(nèi)容比較。 在研究hashcode的用法,發(fā)現(xiàn)自己對(duì)equals的理解還不夠深,廢話少說,繼續(xù)專研,記錄如下: 要想搞清楚equals和==的區(qū)別,就先要搞清楚JAVA的數(shù)據(jù)類型: showImg(https://segmentfault.co...

    ixlei 評(píng)論0 收藏0
  • 夯實(shí)Java:從面向?qū)ο笳f起

    摘要:面向?qū)ο笈c面向過程的區(qū)別要知道,二者并不是非此即彼,而是相輔相成的。而面向過程,則在微觀上對(duì)對(duì)象內(nèi)部進(jìn)行具體的實(shí)現(xiàn)。面向?qū)ο蟮娜筇匦哉f到面向?qū)ο?,就不得不說其三大特性封裝繼承和多態(tài)。封裝封裝是面向?qū)ο笞罨A(chǔ)的特性。 作者:伯特出處:github.com/ruicbAndroid/LoulanPlan聲明:本文出自伯特的《LoulanPlan》,轉(zhuǎn)載務(wù)必注明作者及出處。 剛學(xué)習(xí) Jav...

    hearaway 評(píng)論0 收藏0
  • 夯實(shí)基礎(chǔ)-作用域閉包

    摘要:作用域分類作用域共有兩種主要的工作模型。換句話說,作用域鏈?zhǔn)腔谡{(diào)用棧的,而不是代碼中的作用域嵌套。詞法作用域詞法作用域中,又可分為全局作用域,函數(shù)作用域和塊級(jí)作用域。 一篇鞏固基礎(chǔ)的文章,也可能是一系列的文章,梳理知識(shí)的遺漏點(diǎn),同時(shí)也探究很多理所當(dāng)然的事情背后的原理。 為什么探究基礎(chǔ)?因?yàn)槟悴蝗ッ嬖嚹憔筒恢阑A(chǔ)有多重要,或者是說當(dāng)你的工作經(jīng)歷沒有亮點(diǎn)的時(shí)候,基礎(chǔ)就是檢驗(yàn)?zāi)愫脡牡囊豁?xiàng)...

    daydream 評(píng)論0 收藏0
  • 夯實(shí)基礎(chǔ)js

    摘要:函數(shù)聲明函數(shù)表達(dá)式表達(dá)式定義的函數(shù),成為匿名函數(shù)。匿名函數(shù)沒有函數(shù)提升。一種數(shù)據(jù)類型,它的實(shí)例是唯一且不可改變的。和是本語言的其他兩個(gè)基本要素??傊?,這些也帶來了對(duì)象字面值和類聲明緊密聯(lián)系起來,讓基于對(duì)象的設(shè)計(jì)得益于一些同樣的便利。 聲明(Declarations) undefined值在布爾類型環(huán)境中會(huì)被當(dāng)作false。 數(shù)值類型環(huán)境中undefined值會(huì)被轉(zhuǎn)換為NaN。 對(duì)一個(gè)空...

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

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

0條評(píng)論

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