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

資訊專欄INFORMATION COLUMN

JavaScript || 類和模塊

CoorChice / 2195人閱讀

摘要:屬性每個(gè)函數(shù)默認(rèn)有屬性方法返回的函數(shù)除外,其值為構(gòu)造函數(shù)創(chuàng)建對象繼承的對象。其思路使用原型鏈實(shí)現(xiàn)原型屬性和方法的繼承通過借用構(gòu)造函數(shù)實(shí)現(xiàn)實(shí)例屬性繼承。

1 類和模塊

每個(gè)獨(dú)立的JavaScript對象都是一個(gè)屬性的集合,獨(dú)立對象間沒有任何關(guān)系

ES5中的類是基于原型繼承實(shí)現(xiàn)的:如果兩個(gè)對象從同一個(gè)原型對象繼承屬性,稱兩個(gè)對象為同一個(gè)類的實(shí)例。r instanceof Range.prototype操作符是檢查對象r是否繼承自Range.prototype

JavaScript中的類可以動(dòng)態(tài)繼承

1.1 類和原型

JavaScript中所有類的實(shí)例都從同一個(gè)原型對象上繼承屬性。原型對象是函數(shù)的prototype屬性,每個(gè)函數(shù)都有。Function.bind()方法返回的函數(shù)沒有prototype屬性。

工廠方法:顯式創(chuàng)建一個(gè)對象,并將其作為返回值

1.2 類和構(gòu)造函數(shù)

構(gòu)造函數(shù)用來初始化新創(chuàng)建的對象,每個(gè)新創(chuàng)建對象都繼承了構(gòu)造函數(shù)的prototype屬性指向的原型對象。

關(guān)于構(gòu)造函數(shù)的約定:

構(gòu)造函數(shù)的首字母大寫;

構(gòu)造函數(shù)必須通過new關(guān)鍵字調(diào)用才能創(chuàng)建對象,否則與普通函數(shù)無異;

原型對象必須通過Range.prototype引用

通過new關(guān)鍵字調(diào)用構(gòu)造函數(shù)時(shí),先創(chuàng)建一個(gè)空對象,將構(gòu)造函數(shù)的this綁定到該對象;然后利用構(gòu)造函數(shù)初始化該對象

function Range(from, to) {
  this.from = from;
  this.to = to;
}
// 新創(chuàng)建的所有對象都繼承這個(gè)原型對象
Range.prototype = {   // 重置原型對象的constructor屬性
  // 判斷x是否在范圍之內(nèi)
  includes: function(x) {return this.from <= x && x <= this.to;},
  // 對于范圍內(nèi)的整數(shù)調(diào)用一次f方法
  foreach: function(f) {
    for(var x=Math.ceil(this.from); x<=this.to; x++) {
        f(x);
    }
  },
  toString: function() {return "(" + this.from + "..." + this.to + ")";}
};

var r = new Range(1, 3);
console.log(r instanceof Range);  // true
r.foreach(console.log);   // 1 2 3
console.log(Range.prototype.constructor); // 原型對象的constructor屬性被重置,不再指向Range()
1.3 構(gòu)造函數(shù)和類的標(biāo)識

原型對象是類的唯一標(biāo)識:當(dāng)且僅當(dāng)兩個(gè)對象繼承自同一個(gè)原型對象時(shí),他們才屬于同一個(gè)類的實(shí)例。

r instanceof Range.prototype操作符是檢查對象r是否繼承自Range.prototype

1.4 constructor屬性

原型對象中的constructor屬性是構(gòu)造函數(shù)的引用,但如果直接用字面量對象重寫Range.prototype,新對象中沒有constructor屬性,會(huì)默認(rèn)指向Object()構(gòu)造函數(shù)。

重置constructor屬性指向的方法:

// 重置constructor屬性的方法:
// 1 顯式為原型添加一個(gè)構(gòu)造函數(shù)屬性
Range.prototype = {
  constructor: Range,   // 顯式增加指向Range的constructor屬性
  includes: function(x) {return this.from <= x && x <= this.to;},
  foreach: function(f) {
    for(var x=Math.ceil(this.from); x<=this.to; x++) {
        f(x);
    }
  },
  toString: function() {return "(" + this.from + "..." + this.to + ")";}
};

// 2 依次為原型對象添加方法
Range.prototype.includes = function(x) {
  return this.from <= x && x <= this.to;
};
Range.prototype.foreach = function(a) {
  for(var a=Math.ceil(this.from); a<=this.to; a++) {
      f(a);
    }
};
Range.prototype.toString = function(x) {
  return "(" + this.from + "..." + this.to + ")";
};
2 類的補(bǔ)充 2.1 JavaScript中的函數(shù)

JavaScript中類中的函數(shù)以值的形式出現(xiàn),如果一個(gè)屬性值是函數(shù),稱其為方法。

類的三種對象:

構(gòu)造函數(shù)對象:定義類名,任何添加到構(gòu)造函數(shù)對象本身的屬性都是類字段或類方法

原型對象:原型對象的所有屬性都被實(shí)例對象繼承。

實(shí)例對象:類的每個(gè)實(shí)例對象都是獨(dú)立對象,直接為每個(gè)實(shí)例對象定義的屬性不會(huì)被其他實(shí)例共享。實(shí)例方法與屬性

/*
 * Complex用于描述復(fù)數(shù)類
 * 復(fù)數(shù)是實(shí)數(shù)與虛數(shù)之和,虛數(shù)i的平方為-1
 */
function Complex(real, imaginary) {
    if(isNaN(real) || isNaN(imaginary)) {   // 確保兩個(gè)參數(shù)都是數(shù)字
        throw new TypeError();
    }
    this.r = real;
    this.i = imaginary;
}
// 兩個(gè)復(fù)數(shù)對象之和為一個(gè)新的復(fù)數(shù)對象,使用this代表當(dāng)前復(fù)數(shù)對象
Complex.prototype.add = function(that) {
    return new Complex(this.r + that.r, this.i + that.i); 
};

Complex.prototype.multiply = function(that) {
    return new Complex(this.r * that.r - this.i * that.i, this.r * that.i + this.i * that.r);
};
// 復(fù)數(shù)對象的模:原點(diǎn)(0, 0)到復(fù)平面的距離
Complex.prototype.mag = function() {
    return Math.sqrt(this.r * this.r + this.i * this.i)
};
// 復(fù)數(shù)求負(fù)運(yùn)算
Complex.prototype.neg = function() {
    return new Complex(-this.r, -this.i);
};
// 將復(fù)數(shù)轉(zhuǎn)化為字符串
Complex.prototype.toString = function() {
    return "{" + this.r + "," + this.i + "}";
};
// 當(dāng)前復(fù)數(shù)對象是否與另外一個(gè)復(fù)數(shù)對象值相等
Complex.prototype.equal = function(that) {
    return that != null && that.constructor === Complex && this.r === that. r && this.i === that.i;
};

// 類屬性
Complex.ZERO = new Complex(0, 0);
Complex.ONE = new Complex(1, 0);
Complex.I = new Complex(0, 1);

// 類方法:將實(shí)例對象toString()方法返回的字符串解析為一個(gè)Complex對象
// 或拋出類型錯(cuò)誤異常
Complex._format = /^{([^,]+),([^}]+)}$/;
Complex.parse = function(s) {
    try {  // 假設(shè)解析成功
        var m = Complex._format.exec(s);
        return new Complex(parseFloat(m[1]), parseFloat(m[2]);
    } catch(e) {
        throw new TypeError("can"t parse " + s + "as a complex number");
    }
};

2.2 類的擴(kuò)充

JavaScript中基于原型對象的繼承機(jī)制是動(dòng)態(tài)的:原型對象的屬性發(fā)生變化,會(huì)影響所有繼承該原型對象的實(shí)例對象,即使實(shí)例對象已經(jīng)定義。(原理應(yīng)該是實(shí)例對象中只是保存指向原型對象的引用

不推薦直接在prototype對象上添加屬性或方法,ES5之前不能設(shè)置添加的屬性和方法為不可枚舉,會(huì)被for-in循環(huán)遍歷,ES5中通過Object.defineProperty()方法設(shè)置對象屬性。

2.3 類和類型

使用typeof操作符可以區(qū)分基本數(shù)據(jù)類型:undefined、null、numberstring、function、objectboolean。要區(qū)分?jǐn)?shù)組,有兩種方法:

ES5中的Array.isArray()方法

typeof o === "object" && Object.prototype.toString.call(o).slice(8, -1) === "Array"

區(qū)分自定義類型

使用typeof操作符并不能區(qū)分自定義類型:instanceof操作符、constructor屬性和構(gòu)造函數(shù)名稱三種方式可以區(qū)分自定義類型,但各自與各自的缺點(diǎn)

1 instanceof操作符

如果對象o繼承自對象c.prototype,o instanceof c返回true,缺點(diǎn)是不能返回類名稱,只能檢測對象是否屬于某個(gè)類。其中c.prototype可以是原型鏈上的對象

使用c.prototype.isPrototypeOf(o)方法可以檢測o繼承的原型鏈上是否有原型對象c.prototype

2 constructor屬性

每個(gè)函數(shù)默認(rèn)有prototype屬性(bind()方法返回的函數(shù)除外),其值為構(gòu)造函數(shù)創(chuàng)建對象繼承的對象。原型對象constructor屬性指向構(gòu)造函數(shù)。

缺點(diǎn)是并非所有對象都帶有constructor屬性。

function typeAndValue(x) {
    if(x == null || x == undefined) {
        return "";  //null和undefined沒有構(gòu)造函數(shù)
    }
    switch (x.constructor) {
        case Number: return "Number: " + x;  // 原始類型
        case String: return "String: " + x;
        case Date: return "Date: " + x;      // 內(nèi)置類型
        case RegExp: return "RegExp: " + x;
        case Complex: return "Complex: " + x;  // 自定義類型
    }
};
3 構(gòu)造器函數(shù)的名稱

在多個(gè)執(zhí)行上下文中都存在構(gòu)造器函數(shù)的副本時(shí),instanceof操作符與constructor屬性檢測結(jié)果會(huì)出錯(cuò),但是構(gòu)造器函數(shù)本身的名稱沒有改變,可以作為標(biāo)識

4 鴨子類型

可以向鴨子一樣走路、游泳并且嘎嘎叫的鳥就是鴨子。

以部分特征屬性來描述一類對象(關(guān)注對象能做什么,弱化對象的類型)

3 繼承

許多OO語言支持接口繼承與實(shí)現(xiàn)繼承。但是ECMAScript沒有函數(shù)簽名,只支持實(shí)現(xiàn)繼承,繼承的實(shí)現(xiàn)主要依賴于原型鏈

3.1 原型鏈

原型鏈?zhǔn)紼CMAScript實(shí)現(xiàn)繼承的主要方法:子類的原型對象是父類的實(shí)例對象。

構(gòu)造函數(shù)、原型與實(shí)例的關(guān)系:

構(gòu)造函數(shù)的prototype屬性指向原型對象;

原型對象的constructor屬性指向構(gòu)造函數(shù);

實(shí)例的__proto__屬性指向原型對象,實(shí)例與構(gòu)造函數(shù)沒有直接聯(lián)系

SubType的原型重寫為SuperType的實(shí)例對象,新原型對象作為SuperType一個(gè)實(shí)例擁有全部屬性和方法,內(nèi)部__proto__屬性指向SuperType的原型。

instance指向SubType的原型,SubType的原型指向SuperType的原型。形成一條原型鏈:原型鏈的搜索機(jī)制。先搜索實(shí)例對象instance,再搜索Subype的原型,再搜索SuperType的原型,依次向上

// 父類
function SuperType() {
    this.property = true;    
}
SuperType.prototype.getSuperValue = function() {
    return this.property;
}

// 子類
function SubType() {
    this.subProperty = false;
}
// 子類的原型對象是父類的實(shí)例對象(其__proto__屬性指向父類的原型對象)
SubType.prototype = new SuperType();

SubType.prototype.getSubValue = function() {
    return this.subProperty;
}

var instance = new SubType();
instance.getSuperValue();   // true,子類調(diào)用父類的方法

注:實(shí)例對象instance的原型的構(gòu)造函數(shù)不是SubType,而是SuperType。因?yàn)橹刂?b>SubType.prototype的指向,但是沒有重置construtor的指向

console.log(instance.__proto__.constructor);  // function SuperType() {native code}
1原型鏈末端

所有引用類型都繼承自Object,函數(shù)的默認(rèn)原型是Object的實(shí)例,默認(rèn)原型內(nèi)包含指向Object.prototype的引用,這是所有自定義類型都會(huì)繼承toString()、valueOf()等方法的根本原因

Object.prototype沒有原型,其原型為null,即

Object.prototype.__proto__ === null;  // true

Object.prototype.__proto__是原型鏈的末端,出口

2原型與實(shí)例的關(guān)系

使用instanceof操作符與isPrototypeOf()方法:

instance instanceof Object;    // true
instance instanceof SuperType;    // true
instance instanceof SubType;    // true

Object.prototype.isPrototypeOf(instance);   // true
SuperType.prototype.isPrototypeOf(instance);   // true
SubType.prototype.isPrototypeOf(instance);   // true
3 謹(jǐn)慎定義子類中方法的位置

如果在子類中定義新方法或者重寫父類的方法,必須子類替換原型語句SubType.prototype = new SuperType();之后,否則不起作用。

function SuperType() {
    this.property = true;    
}
SuperType.prototype.getSuperValue = function() {
    return this.property;
}

// 子類
function SubType() {
    this.subProperty = false;
}
// 子類的原型對象是父類的實(shí)例對象(其__proto__屬性指向父類的原型對象)
SubType.prototype = new SuperType();

// 添加新方法
SubType.prototype.getSubValue = function() {
    return this.subProperty;
}
// 重寫父類中的方法
SuperType.prototype.getSuperValue = function() {
    return false;
}

var instance = new SubType();
instance.getSuperValue();   // false

在使用原型鏈實(shí)現(xiàn)繼承時(shí),不能使用字面量方式創(chuàng)建原型對象,否則會(huì)切斷原型鏈,將原型對象重行指向字面量對象

function SuperType() {
    this.property = true;    
}
SuperType.prototype.getSuperValue = function() {
    return this.property;
}

// 子類
function SubType() {
    this.subProperty = false;
}
// 子類的原型對象是父類的實(shí)例對象(其__proto__屬性指向父類的原型對象)
SubType.prototype = new SuperType();

// 使用字面量方式添加新方法,使上一行代碼無效
SubType.prototype = {
    getSubValue: function() {
        return this.subProperty;
    },
    getSuperValue: function() {
        return false;
    }
}

var instance = new SubType();
instance.getSuperValue();   // false
4 原型鏈的問題

對于包含引用類型值的原型對象:所有勢力共享原型的屬性,如果其屬性值是引用類型:在一個(gè)實(shí)例上修改該引用類型的值,會(huì)體現(xiàn)在所有的實(shí)例對象上 。-----所以需要將引用類型值定義在構(gòu)造函數(shù)中,而非原型對象中。

function SuperColor() {
    this.color = ["red", "blue"];   
}

function SubColor() {

}
SubColor.prototype = new SuperColor();   // 子類原型定義為父類的實(shí)例,但是color屬性值為引用類型

var col1 = new SubColor();
col1.color.push("green");
console.log(col1.color);   // ["red", "blue", "green"]

// 注意,所有的實(shí)例對象的color都改變
var col2 = new SubColor();
console.log(col2.color);  // ["red", "blue", "green"]

沒有辦法在不影響所有對象實(shí)例的情況下,向父類的構(gòu)造函數(shù)傳遞參數(shù)。

基于上述2點(diǎn)原因,很少多帶帶使用原型鏈

3.2 借用構(gòu)造函數(shù)constructor stealing

在子類中,利用創(chuàng)建的對象,以方法的形式調(diào)用父類構(gòu)造器函數(shù),父類構(gòu)造器函數(shù)僅用于初始化子類中創(chuàng)建的對象

基本思想:在子類構(gòu)造函數(shù)內(nèi)部調(diào)用父類構(gòu)造函數(shù)。因?yàn)楹瘮?shù)只是特定環(huán)境中執(zhí)行代碼的對象,可以使用call()apply()方法在新創(chuàng)建對象上執(zhí)行構(gòu)造函數(shù)

1.通過new調(diào)用SubColor():本質(zhì)先創(chuàng)建一個(gè)對象,將其綁定到this再利用this調(diào)用函數(shù)SuperColor(),設(shè)置this.color屬性值

2.每次調(diào)用new SubColor()創(chuàng)建的都是獨(dú)立的對象,所以不影響

function SuperColor() {
    this.color = ["red", "blue"];   
}

function SubColor() {
    // 繼承SuperColor
    // 使用新創(chuàng)建的對象this來調(diào)用SuperColor()函數(shù),設(shè)置this.color屬性值
    // 每次調(diào)用new SubColor()創(chuàng)建的都是獨(dú)立的對象,所以不影響
    SuperColor.call(this);  
}

var col3 = new SubColor();
col1.color.push("green");
console.log(col3.color);   // ["red", "blue", "green"]

var col4 = new SubColor();
console.log(col4.color);  // ["red", "blue"]
傳遞參數(shù)

通過借用構(gòu)造器函數(shù)可以向父類構(gòu)造函數(shù)傳遞參數(shù)。將參數(shù)掛載在call()apply()方法中:將父類構(gòu)造器哈數(shù)僅用作初始化對象用

function SuperType(name) {
    this.name = name;
}
function SubType() {
    // 繼承SuperType,同時(shí)傳遞參數(shù)"Tracy"
    SuperType.call(this, "Tracy");

    this.age = 23; // 實(shí)例屬性
}

var kyxy = new SubType();
console.log(kyxy.name);   // "Tracy"
console.log(kyxy.age);    //  23
借用構(gòu)造器函數(shù)的問題

如果僅僅使用借用構(gòu)造函數(shù)模式,只能講方法都定義在構(gòu)造函數(shù)中,不能復(fù)用函數(shù),所以借用構(gòu)造函數(shù)模式很少多帶帶使用

3.3 組合繼承

將原型鏈模式與借用構(gòu)造函數(shù)模式組合,發(fā)揮二者的長處。其思路:

使用原型鏈實(shí)現(xiàn)原型屬性和方法的繼承;通過借用構(gòu)造函數(shù)實(shí)現(xiàn)實(shí)例屬性繼承。組合繼承避免原型鏈與借用構(gòu)造函數(shù)的缺點(diǎn),融合優(yōu)點(diǎn),是ECMAScript中最常用的的繼承模式

首先使用借用構(gòu)造函數(shù)模式繼承實(shí)例屬性

再使用原型鏈模式繼承原型的屬性與方法

借用構(gòu)造函數(shù)模式:利用子類創(chuàng)建空對象,將父類的實(shí)例屬性拷貝到子類中。因?yàn)槊總€(gè)子類是獨(dú)立的對象,所以享有父類的拷貝也是相互獨(dú)立的

實(shí)例間共享的原型對象中的屬性依然通過原型鏈模式實(shí)現(xiàn)

function SuperType(name) {
    this.name = name;
    this.color = ["red", "blue"];
}
SuperType.prototype.sayName = function() {
    coonsle.log(this.name);
}

function SubType(name, age) {
    // 實(shí)例屬性的繼承(不再是引用,而是多帶帶一份拷貝)
    SuperType.call(this, name);

    this.age = age;
}
// 原型屬性與方法的繼承
SubType.prototype = new SuperType();
// 重置原型對象constructor的指向
SubType.prototype.constructor = SubType;
SubType.prototype.sayAge = function() {
    console.log(this.age);
}

var p1 = new SubType("Kyxy", 23);
p1.color.push("black");
p1.sayAge();   // 23
p1.sayName();   // "Kyxy"
p1.color;     // ["red", "blue", "black"]

var p2 = new SubType("Tracy", 23);
p2.color;   // ["red", "blue"]

3.4 總結(jié)

ECMAScript中創(chuàng)建對象的模式:

工廠模式

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

原型模式

ECMAScript中主要的繼承模式是組合繼承:綜合原型鏈模式與借用構(gòu)造函數(shù)模式的優(yōu)點(diǎn)。

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

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

相關(guān)文章

  • erget源碼分析(2):全局哈希基類和全局異步函數(shù)對象接口

    摘要:異步函數(shù)對象接口,包含和兩個(gè)成員方法。哈希計(jì)數(shù)在整個(gè)的源碼中都沒有找到和方法的調(diào)用,這兩個(gè)方法的具體作用是在原生中實(shí)現(xiàn)類式繼承和私有屬性一類的功能。 文件結(jié)構(gòu) utils/HashObject.ts文件:showImg(https://segmentfault.com/img/bVZpuq?w=642&h=472); 首先解釋一下文件結(jié)構(gòu)圖 __extends方法 通過原型對象模擬類...

    godlong_X 評論0 收藏0
  • [翻]ECMAScript 6 特性速覽

    摘要:類總所周知,不像其他面向?qū)ο笳Z言那樣支持類,但是可以通過函數(shù)和原型來模擬類。如果你學(xué)習(xí)過或者其他面向?qū)ο笳Z言的話,你會(huì)覺得很熟悉。結(jié)論下一個(gè)版本的會(huì)帶來一個(gè)更加簡單更加友好的語法來幫助那些從面向?qū)ο笳Z言轉(zhuǎn)過來的開發(fā)者的學(xué)習(xí)。 原文地址:http://www.frontendjournal.com/javascript-es6-learn-important-features-in-a-...

    CoderStudy 評論0 收藏0
  • 聊聊畢業(yè)設(shè)計(jì)系列 --- 項(xiàng)目介紹

    摘要:又將整個(gè)文藝類閱讀系統(tǒng)的業(yè)務(wù)劃分為兩大部分,分別是面向管理員和合作作者的后臺(tái)管理系統(tǒng)和面向用戶的移動(dòng)端,系統(tǒng)的需求分析將圍繞這兩部分進(jìn)行展開。 效果展示 showImg(https://user-gold-cdn.xitu.io/2018/8/26/16576a709bd02f5f?w=1409&h=521&f=gif&s=30128195); showImg(https://user...

    Pink 評論0 收藏0
  • 聊聊畢業(yè)設(shè)計(jì)系列 --- 項(xiàng)目介紹

    摘要:又將整個(gè)文藝類閱讀系統(tǒng)的業(yè)務(wù)劃分為兩大部分,分別是面向管理員和合作作者的后臺(tái)管理系統(tǒng)和面向用戶的移動(dòng)端,系統(tǒng)的需求分析將圍繞這兩部分進(jìn)行展開。 效果展示 showImg(https://user-gold-cdn.xitu.io/2018/8/26/16576a709bd02f5f?w=1409&h=521&f=gif&s=30128195); showImg(https://user...

    villainhr 評論0 收藏0

發(fā)表評論

0條評論

閱讀需要支付1元查看
<