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

資訊專(zhuān)欄INFORMATION COLUMN

JS對(duì)象小結(jié)

mzlogin / 1063人閱讀

摘要:返回新對(duì)象構(gòu)造函數(shù)與其他函數(shù)的唯一區(qū)別,就在于調(diào)用它們的方式不同。在默認(rèn)情況下,所有原型對(duì)象都會(huì)自動(dòng)獲得一個(gè)構(gòu)造函數(shù)屬性,這個(gè)屬性是一個(gè)指向?qū)傩运诤瘮?shù)的指針。

對(duì)象 1.對(duì)象的定義

“無(wú)序?qū)傩缘募?,其屬性可以包含基本值,?duì)象或者函數(shù)”。每個(gè)屬性都是一個(gè)名/值對(duì)。屬性名是字符串,因此我們可以把對(duì)象看成是從字符串到值的映射。

2.對(duì)象的創(chuàng)建

=======

通過(guò)new創(chuàng)建對(duì)象
new運(yùn)算符創(chuàng)建并初始化一個(gè)新對(duì)象。關(guān)鍵字new后跟隨一個(gè)函數(shù)調(diào)用,這個(gè)函數(shù)被稱(chēng)為構(gòu)造函數(shù)。

var person = new Object();    //創(chuàng)建一個(gè)空對(duì)象

person.name = "Jack";         //添加屬性
person.age = 20;

person.sayName = function(){  //添加方法
    alert(this.name);
}

對(duì)象字面量
對(duì)象字面量是一個(gè)表達(dá)式。每次運(yùn)算都創(chuàng)建并初始化一個(gè)新的對(duì)象。每次計(jì)算對(duì)象直接量的時(shí)候,也都會(huì)計(jì)算它的每個(gè)屬性的值。

var person = {
    name: "Jack",
    age: 20,
    sayName: function(){
        alert(this.name);
    }
};

原型
每一個(gè)JS對(duì)象(null除外)都與另一個(gè)對(duì)象相關(guān)聯(lián)?!傲硪粋€(gè)”對(duì)象就是我們所熟知的原型,每一個(gè)對(duì)象都從原型繼承屬性和方法。
所有通過(guò)對(duì)象字面量創(chuàng)建的對(duì)象都具有同一個(gè)原型對(duì)象,可以通過(guò)Object.prototype獲得對(duì)原型對(duì)象的引用。通過(guò)關(guān)鍵字new和構(gòu)造函數(shù)調(diào)用創(chuàng)建的對(duì)象的原型就是構(gòu)造函數(shù)的prototype屬性的值。
Object.prototype沒(méi)有原型,不繼承任何屬性。

Object.create()
ES5定義了一個(gè)名為Object.create的方法,他創(chuàng)建一個(gè)新對(duì)象,其中第一個(gè)參數(shù)是這個(gè)對(duì)象的原型,第二個(gè)參數(shù)用以對(duì)對(duì)象的屬性進(jìn)行進(jìn)一步描述。
可以通過(guò)任意原型創(chuàng)建新對(duì)象,換句話說(shuō),可以使任意對(duì)象可繼承。

var o1 = Object.create(Object.prototype);

var o2 = Object.create(null);        //不繼承任何屬性和方法

new一個(gè)對(duì)象
擴(kuò)展:new一個(gè)對(duì)象時(shí)做了什么?
舉例:使用new關(guān)鍵字創(chuàng)建對(duì)象new ClassA()

1.創(chuàng)建一個(gè)空對(duì)象

var obj = {};

2.設(shè)置新對(duì)象的__proto__指向構(gòu)造函數(shù)的原型對(duì)象

obj.__proto__ = ClassA.prototype;

3.將構(gòu)造函數(shù)的作用域賦給新對(duì)象

ClassA.call(obj);

4.執(zhí)行構(gòu)造函數(shù)中的代碼并返回新對(duì)象

3.屬性類(lèi)型

數(shù)據(jù)屬性
數(shù)據(jù)屬性包含一個(gè)數(shù)據(jù)值的位置。在這個(gè)位置可以讀取和寫(xiě)入值。
[[Configurable]]:表示能否通過(guò) delete 刪除屬性從而重新定義屬性,能否修改屬性的特性,或者能否把屬性修改為訪問(wèn)器屬性。
[[Enumerable]]:表示能否通過(guò) for-in循環(huán)遍歷屬性。
[[Writable]]:表示能否修改屬性的值。
[[Value]]:包含這個(gè)屬性的數(shù)據(jù)值。

訪問(wèn)器屬性
訪問(wèn)器屬性不包含數(shù)據(jù)值,包含一對(duì)兒getter和setter函數(shù)(非必需)。訪問(wèn)器屬性不能直接定義,要通過(guò)Object.defineProperty()來(lái)定義。
[[Get]]:在讀取屬性時(shí)調(diào)用的函數(shù)。
[[Set]]:在寫(xiě)入屬性時(shí)調(diào)用的函數(shù)。

定義多個(gè)屬性
利用Object.defineProperties()方法可以通過(guò)描述符一次定義多個(gè)屬性。這個(gè)方法接收兩個(gè)對(duì)象參數(shù):第一個(gè)對(duì)象是要添加和修改其屬性的對(duì)象,第二個(gè)對(duì)象的屬性與第一個(gè)對(duì)象中要添加或修改的屬性一一對(duì)應(yīng)。

讀取屬性的特性
使用 ES5 的 Object.getOwnPropertyDescriptor()方法,可以取得給定屬性的描述符。這個(gè)方法接收兩個(gè)參數(shù):屬性所在的對(duì)象和要讀取其描述符的屬性名稱(chēng)。返回值是一個(gè)對(duì)象。

4.創(chuàng)建對(duì)象的模式

使用小結(jié)1中的方法創(chuàng)建對(duì)象有明顯的缺點(diǎn):使用同一個(gè)接口創(chuàng)建很多對(duì)象,會(huì)產(chǎn)生大量的重復(fù)代碼。因此出現(xiàn)了各種創(chuàng)建對(duì)象的模式。

工廠模式
在一個(gè)函數(shù)中創(chuàng)建好對(duì)象,然后把函數(shù)返回。

function createPerson(name,age,job){
    var o=new Object();
    o.name=name;
    o.age=age;
    o.job=job;
    o.sayName=function(){
        alert(this.name);
    };
    return o;
}

var person1=createPerson("Jack",20,"Software Engineer");
var person2=createPerson("Tom",22,"Project Manager");

缺點(diǎn):沒(méi)有解決對(duì)象識(shí)別的問(wèn)題,即怎么知道一個(gè)對(duì)象的類(lèi)型。

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

像Object和Array這樣的原生構(gòu)造函數(shù),在運(yùn)行時(shí)會(huì)自動(dòng)出現(xiàn)在執(zhí)行環(huán)境。此外,也可以創(chuàng)建自定義的構(gòu)造函數(shù),從而定義自定義對(duì)象類(lèi)型的屬性和方法。

function Person(name,age,job){
    this.name=name;
    this.age=age;
    this.job=job;
    this.sayName=function(){
        alert(this.name);
    };
}

var person1=new Person("Jack",20,"Software Engineer");
var person2=new Person("Tom",22,"Project Manager");

與工廠模式比:

沒(méi)有顯式地創(chuàng)建對(duì)象

直接將屬性和方法賦予了this對(duì)象

沒(méi)有return語(yǔ)句

要?jiǎng)?chuàng)建Person實(shí)例,必須使用new操作符,用這種方式調(diào)用的構(gòu)造函數(shù)會(huì)經(jīng)歷以下幾個(gè)步驟:

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

新對(duì)象的_proto_指向構(gòu)造函數(shù)的原型對(duì)象

將構(gòu)造函數(shù)的作用域賦值給新對(duì)象

執(zhí)行構(gòu)造函數(shù)內(nèi)部的代碼,將屬性添加給person中的this對(duì)象。

返回新對(duì)象

構(gòu)造函數(shù)與其他函數(shù)的唯一區(qū)別,就在于調(diào)用它們的方式不同。

缺點(diǎn):構(gòu)造函數(shù)內(nèi)部的方法會(huì)被重復(fù)創(chuàng)建,不同實(shí)例內(nèi)的同名函數(shù)是不相等的??赏ㄟ^(guò)將方法移到構(gòu)造函數(shù)外部解決這一問(wèn)題,但面臨新問(wèn)題:封裝性不好。

原型模式:

我們創(chuàng)建的每個(gè)函數(shù)都有一個(gè)prototype屬性,這個(gè)屬性是一個(gè)指針,指向一個(gè)對(duì)象,而這個(gè)對(duì)象的用途是包含可以由特定類(lèi)型的所有實(shí)例共享的屬性和方法。(prototype就是通過(guò)調(diào)用構(gòu)造函數(shù)而創(chuàng)建的那個(gè)對(duì)象實(shí)例的原型對(duì)象)。

使用原型對(duì)象的好處是可以讓所有對(duì)象實(shí)例共享它所包含的屬性和方法。換句話說(shuō),不必在構(gòu)造函數(shù)中定義對(duì)象實(shí)例的信息,而是可以將這些信息直接添加到原型對(duì)象中。

function Person(){
}

Person.prototype.name="Jack";
Person.prototype.age=20;
Person.prototype.job="Software Engineer";
Person.prototype.sayName=function(){
    alert(this.name);
};

var person1=new Person();
person1.sayName();//"Jack"

理解原型對(duì)象

無(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ù)的指針。

原型對(duì)象的問(wèn)題:

它省略了為構(gòu)造函數(shù)傳遞初始化參數(shù)這一環(huán)節(jié),結(jié)果所有實(shí)例在默認(rèn)情況下都將取得相同的屬性值,雖然這會(huì)在一定程度帶來(lái)一定的不便,但不是最大的問(wèn)題,最大的問(wèn)題是由其共享的本性所決定的。

對(duì)于包含基本值的屬性可以通過(guò)在實(shí)例上添加一個(gè)同名屬性隱藏原型中的屬性。然后,對(duì)于包含引用數(shù)據(jù)類(lèi)型的值來(lái)說(shuō),會(huì)導(dǎo)致問(wèn)題。

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

這是創(chuàng)建自定義類(lèi)型的最常見(jiàn)的方式。

構(gòu)造函數(shù)模式用于定義實(shí)例屬性,而原型模式用于定義方法和共享的屬性。所以每個(gè)實(shí)例都會(huì)有自己的一份實(shí)例屬性的副本,但同時(shí)共享著對(duì)方法的引用,最大限度的節(jié)省了內(nèi)存。同時(shí)支持向構(gòu)造函數(shù)傳遞參數(shù)。

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

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

var person1=new Person(...);

動(dòng)態(tài)原型模式

function Person(name,age,job){
    this.name=name;
    this.age=age;
    this.job=job;

    if(typeof this.sayName!="function"){
        Person.prototype.sayName=function(){
            alert(this.name);
        };
    }
}

這里只有sayName()不存在的情況下,才會(huì)將它添加到原型中,這段代碼只會(huì)在初次調(diào)用構(gòu)造函數(shù)時(shí)才執(zhí)行。這里對(duì)原型所做的修改,能夠立刻在所有實(shí)例中得到反映。

5.繼承

JS實(shí)現(xiàn)繼承的幾種方式

定義一個(gè)父類(lèi)

//定義一個(gè)動(dòng)物類(lèi)
function Animal(name){
    //屬性
    this.name = name || "Animal";
    //實(shí)例方法
    this.sleep = function(){
        console.log(this.name + " is sleeping~");
    }
}

//原型方法
Animal.prototype.eat = function(food){
    console.log(this.name + " is eating " + food);
}

原型鏈繼承
構(gòu)造函數(shù)、實(shí)例對(duì)象和原型對(duì)象的關(guān)系:

如果使一個(gè)原型對(duì)象等于另一個(gè)對(duì)象的實(shí)例,此時(shí)的原型對(duì)象將包含一個(gè)指向另一個(gè)原型的指針,相應(yīng)地,另一個(gè)原型中也包含著一個(gè)指向另一個(gè)構(gòu)造器函數(shù)的指針。假如另一個(gè)原型又是另一個(gè)類(lèi)型的實(shí)例,如此層層遞進(jìn),就構(gòu)成了實(shí)例與原型的鏈條。這就是原型鏈的基本概念。

function Cat(){
}
Cat.prototype = new Animal();
Cat.prototype.name = "cat";

// Test Code
var cat = new Cat();
console.log(cat.name);
console.log(cat.eat("fish"));
console.log(cat.sleep());
console.log(cat instanceof Animal); //true 
console.log(cat instanceof Cat); //true

原型鏈的問(wèn)題:

來(lái)自原型對(duì)象的引用屬性被所有實(shí)例共享

創(chuàng)建子類(lèi)實(shí)例時(shí),無(wú)法向父類(lèi)構(gòu)造函數(shù)傳遞參數(shù)

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

這種繼承方式的基本思想是在子類(lèi)構(gòu)造函數(shù)的內(nèi)部調(diào)用父類(lèi)的構(gòu)造函數(shù)。

function Cat(){
    Animal.call(this);
    this.name = name || "Tom";
}

// Test Code
var cat = new Cat();
console.log(cat.name);
console.log(cat.sleep());
console.log(cat instanceof Animal); // false
console.log(cat instanceof Cat); // true

構(gòu)造函數(shù)繼承的問(wèn)題:

實(shí)例并不是父類(lèi)的實(shí)例,只是子類(lèi)的實(shí)例

方法都在構(gòu)造函數(shù)中定義,函數(shù)復(fù)用無(wú)從談起

組合繼承

思路是使用原型鏈實(shí)現(xiàn)對(duì)原型屬性和方法的繼承,借用構(gòu)造函數(shù)實(shí)現(xiàn)對(duì)實(shí)例屬性的繼承。

function Cat(){
    Animal.call(this);
    this.name = name || "Tom";
}
Cat.prototype = new Animal();
Cat.prototype.constructor = Cat;

// Test Code
var cat = new Cat();
console.log(cat.name);
console.log(cat.sleep());
console.log(cat instanceof Animal); // true
console.log(cat instanceof Cat); // true

組合繼承的問(wèn)題: 調(diào)用了兩次父類(lèi)構(gòu)造函數(shù),生成了兩份實(shí)例(子類(lèi)實(shí)例將子類(lèi)原型上的同名屬性屏蔽了),會(huì)多消耗一點(diǎn)內(nèi)存。

寄生組合式繼承

通過(guò)寄生方式,砍掉父類(lèi)的實(shí)例屬性,這樣,在調(diào)用兩次父類(lèi)的構(gòu)造的時(shí)候,就不會(huì)初始化兩次實(shí)例方法/屬性,避免的組合繼承的缺點(diǎn)。

function Cat(){
    Animal.call(this);
    this.name = name || "Tom";
}
(function(){
    //創(chuàng)造一個(gè)沒(méi)有實(shí)例方法的類(lèi)
    var Super = function(){};
    Super.prototype = Animal.prototype;
    Cat.prototype = new Super();
    Cat.prototype.constructor = Cat; 
})();

// Test Code
var cat = new Cat();
console.log(cat.name);
console.log(cat.sleep());
console.log(cat instanceof Animal); // true
console.log(cat instanceof Cat); //true

缺點(diǎn): 稍顯復(fù)雜。

拷貝繼承

function Cat(){
    var animal = new Animal();
    for(var p in animal){
        Cat.prototype[p] = animal[p];
    }
    Cat.prototype.name = this.name || "Tom";
}

// Test Code
var cat = new Cat();
console.log(cat.name);
console.log(cat.sleep());
console.log(cat instanceof Animal); // false
console.log(cat instanceof Cat); // true

拷貝繼承存在的問(wèn)題:

效率較低,內(nèi)存占用高(因?yàn)橐截惛割?lèi)的屬性)

無(wú)法獲取父類(lèi)不可枚舉的方法(for-in不能訪問(wèn)到不可枚舉方法)

6.對(duì)象屬性的遍歷

1.for...in
for...in循環(huán)遍歷對(duì)象自身和繼承的可枚舉屬性(不含Symbol屬性)

2.Object.keys(obj)
Object.keys返回一個(gè)數(shù)組,包括對(duì)象自身的(不含繼承的)所有可枚舉屬性(不含Symbol屬性)

3.Object.getOwnPropertyNames(obj)
Object.getOwnPropertyNames返回一個(gè)數(shù)組,包含對(duì)象自身的所有屬性(不含Symbol屬性,但是包括不可枚舉屬性)

4.Object.getOwnPropertySymbols(obj)
Object.getOwnPropertySymbols返回一個(gè)數(shù)組,包含對(duì)象自身的所有Symbol屬性。

5.Reflect.ownKeys(obj)
Reflect.ownKeys返回一個(gè)數(shù)組,包含對(duì)象自身的所有屬性,不管屬性名是Symbol還是字符串,也不管是否可枚舉。

7.對(duì)象的拷貝

對(duì)象的拷貝分為淺拷貝和深拷貝,簡(jiǎn)單來(lái)說(shuō),淺復(fù)制只復(fù)制一層對(duì)象的屬性,而深復(fù)制則遞歸復(fù)制了所有層級(jí)。深拷貝和淺拷貝最根本的區(qū)別在于是否是真正獲取了一個(gè)對(duì)象的復(fù)制實(shí)體,而不是引用。

淺拷貝的實(shí)現(xiàn)

function shallowCopy(obj1) {
  var obj2 = {};
  for (var prop in obj1) {
    if (obj1.hasOwnProperty(prop)) {
      obj2[prop] = obj1[prop];
    }
  }
  return obj2;
}

深拷貝的實(shí)現(xiàn)

// 方法一
JSON.parse(JSON.stringify(obj));

// 方法二
function deepCopy(obj1, obj2){
    var obj2 = obj2 || {};
    for(var prop in obj1) {
        if(typeof obj1[prop] === "object") {
            if(obj1[prop].constructor === Array) {
                obj2[prop] = [];
            } else {
                obj2[prop] = {};
            }
            deepCopy(obj1[prop], obj2[prop]);
        } else {
            obj2[prop] = obj1[prop];
        }
    }
    return obj2;
}

本篇小結(jié)是對(duì)對(duì)象做一個(gè)系統(tǒng)的梳理,主要是在秋招之前供自己復(fù)習(xí),有錯(cuò)誤的地方還請(qǐng)大家指出。

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

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

相關(guān)文章

  • 【讀書(shū)筆記】《高性能JavaScript》

    摘要:性能訪問(wèn)字面量和局部變量的速度是最快的,訪問(wèn)數(shù)組和對(duì)象成員相對(duì)較慢變量標(biāo)識(shí)符解析過(guò)程搜索執(zhí)行環(huán)境的作用域鏈,查找同名標(biāo)識(shí)符。建議將全局變量存儲(chǔ)到局部變量,加快讀寫(xiě)速度。優(yōu)化建議將常用的跨作用域變量存儲(chǔ)到局部變量,然后直接訪問(wèn)局部變量。 缺陷 這本書(shū)是2010年出版的,這本書(shū)談性能是有時(shí)效性的,現(xiàn)在馬上就2018年了,這幾年前端發(fā)展的速度是飛快的,書(shū)里面還有一些內(nèi)容考慮IE6、7、8的東...

    chengjianhua 評(píng)論0 收藏0
  • 高性能JavaScript(文檔)

    摘要:最近在全力整理高性能的文檔,并重新學(xué)習(xí)一遍,放在這里方便大家查看并找到自己需要的知識(shí)點(diǎn)。 最近在全力整理《高性能JavaScript》的文檔,并重新學(xué)習(xí)一遍,放在這里方便大家查看并找到自己需要的知識(shí)點(diǎn)。 前端開(kāi)發(fā)文檔 高性能JavaScript 第1章:加載和執(zhí)行 腳本位置 阻止腳本 無(wú)阻塞的腳本 延遲的腳本 動(dòng)態(tài)腳本元素 XMLHTTPRequest腳本注入 推薦的無(wú)阻塞模式...

    RayKr 評(píng)論0 收藏0
  • javascript小結(jié)

    摘要:一簡(jiǎn)介是一種解釋性的腳本語(yǔ)言代碼不進(jìn)行編譯,主要用來(lái)向頁(yè)面添加交互行為,主要由三部分組成核心,包含基本語(yǔ)法文檔對(duì)象模型瀏覽器對(duì)象模型是一種弱類(lèi)型語(yǔ)言,可用修飾所有的變量不加時(shí)是全局變量二常見(jiàn)事件頁(yè)面或圖片加載完成時(shí)點(diǎn)擊提交按鈕時(shí)注意是在添加 一.簡(jiǎn)介 javascript是一種解釋性的腳本語(yǔ)言(代碼不進(jìn)行編譯),主要用來(lái)向HTML頁(yè)面添加交互行為,主要由三 部分組成:ECMAScrip...

    linkin 評(píng)論0 收藏0
  • JS復(fù)習(xí)--原型鏈小結(jié)

    摘要:為什么需要原型鏈為了實(shí)現(xiàn)繼承,具有相同特性的代碼不需要重復(fù)編寫(xiě),放在構(gòu)造函數(shù)里面,實(shí)例化的對(duì)象都會(huì)擁有里面的屬性了,也就是可以共享屬性和方法。 一段簡(jiǎn)單代碼引入 function Foo() {}; var f1 = new Foo(); showImg(https://segmentfault.com/img/bV4yXs?w=1176&h=944); 1.概念簡(jiǎn)單理解 Foo...

    Gu_Yan 評(píng)論0 收藏0
  • 關(guān)于promise的小結(jié)

    摘要:則是把類(lèi)似的異步處理對(duì)象和處理規(guī)則進(jìn)行規(guī)范化,并按照采用統(tǒng)一的接口來(lái)編寫(xiě),而采取規(guī)定方法之外的寫(xiě)法都會(huì)出錯(cuò)。這個(gè)對(duì)象有一個(gè)方法,指定回調(diào)函數(shù),用于在異步操作執(zhí)行完后執(zhí)行回調(diào)函數(shù)處理。到目前為止,已經(jīng)學(xué)習(xí)了創(chuàng)建對(duì)象和用,方法來(lái)注冊(cè)回調(diào)函數(shù)。 Promise 本文從js的異步處理出發(fā),引入Promise的概念,并且介紹Promise對(duì)象以及其API方法。 js里的異步處理 可以參考這篇文章...

    Tony_Zby 評(píng)論0 收藏0
  • webpack小結(jié)

    摘要:安裝文件夾出現(xiàn)使用解析不了解決使用處理指定出口入口指定處理的文件不想手動(dòng)指定入口與出口文件就創(chuàng)建指定入口出口將出口入口暴露使用打包首先發(fā)現(xiàn)沒(méi)有指定入口與出口尋找文件找到配置后解析執(zhí)行,找到配置對(duì)象拿到對(duì)象后,進(jìn)行打包安裝實(shí)現(xiàn)自動(dòng)打包編 npm i 安裝node_moudles文件夾 dist src css js image main.js ...

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

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

0條評(píng)論

mzlogin

|高級(jí)講師

TA的文章

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