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

資訊專欄INFORMATION COLUMN

溫故js系列(18)-對象&對象使用

keke / 2091人閱讀

摘要:對象創(chuàng)建字面量方式構(gòu)造函數(shù)方式也可以這樣不過這樣的話,為何不選擇字面量方式字面量方式和方式的寫法是等價的,返回的結(jié)果是同種類的對象。構(gòu)造函數(shù)產(chǎn)生實例時,實例通過其對應(yīng)原型對象的訪問對應(yīng)的構(gòu)造函數(shù)對象。

前端學(xué)習(xí):教程&模塊化/規(guī)范化/工程化/優(yōu)化&工具/調(diào)試&值得關(guān)注的博客/Git&面試資源匯總

歡迎提issues斧正:對象&對象使用

Object對象

在 JavaScript 中,對象,是對一些具體事物的一種抽象,所有其他對象都繼承自這個對象。Object 是一個無序集合,將變量和值集合在一起,可以存放任意類型對象(JavaScript中的一切皆對象,這句話應(yīng)該沒有對錯,無論正反兩個方面,支持者都能說出他們的解釋)。

對象創(chuàng)建 字面量方式
var obj = {
    key: "value",
    name : "xzavier",
    sex : "male",
};
構(gòu)造函數(shù)方式
var obj = new Object();
obj.key = "value";
obj.name = "xzavier";
obj.sex = "male";

也可以這樣(不過這樣的話,為何不選擇字面量方式):

var obj = new Object({
    key: "value",
    name : "xzavier",
    sex : "male",
});

字面量方式和new方式的寫法是等價的,返回的結(jié)果是同種類的對象。

字面量方式比較好的是你可以在聲明的時候一次性添多個屬性和值,即鍵/值對;
而構(gòu)造函數(shù)方式,你必須在構(gòu)造完成之后一個一個地添加屬性。

所以,你經(jīng)常都會被建議使用字面量的方式,我們也實踐得非常不錯。很多時候,我們只有在場景需要的情況下才會使用new 構(gòu)造函數(shù)的方式。比如說拋出錯誤、創(chuàng)建含有變量的正則等:

new Error(..)
new RegExp("xzav" + i + "er");

所以,大多情況下我們都使用字面量方式,一般不需要明確地創(chuàng)建對象。JavaScript會在必要的時候自動地將一些基本類型轉(zhuǎn)換為對象類型,以便你能使用對象類型中的屬性:

var x = "xx";
x.length; // 2  擁有String類型對象的屬性
var z = "123.321";
z.toFixed(2); // "123.32" 擁有Number類型對象的方法
內(nèi)置對象

JavaScript中,有很多內(nèi)置的Object的子類型,我們通常稱為內(nèi)置對象,它們實際上是內(nèi)建的函數(shù),每一個都可以作為構(gòu)造函數(shù) new 出一個新構(gòu)造的相應(yīng)子類型的實例,當(dāng)然,也是對象。

String
Number
Boolean
Math
Function
Array
Date
RegExp
Error

如上面所說,創(chuàng)建這些子類型也基本使用字面量的方法。檢測類型的話使用

Object.prototype.toString.call(obj);

檢測的最全。具體參考文章: 數(shù)據(jù)類型檢測

Object.prototype對象

在JavaScript中,幾乎所有對象都是Object的實例。而Object有一個屬性prototype,指向原型對象(js里所有構(gòu)造函數(shù)都有一個prototype屬性,指向原型對象)。我們在實例化一個對象時,實例會繼承原型對象上的屬性和方法。

可以控制臺查看 String.prototype
然后再: var str = new String("xzavier");
我們的str繼承了String.prototype上的屬性和方法,String又繼承了Obeject.prototype上的方法。

不過說是繼承,說是指向引用比較好。因為對象在查找某個屬性的時候,會首先遍歷自身的屬性,如果沒有則會繼續(xù)查找[[Prototype]]引用的對象,如果再沒有則繼續(xù)查找[[Prototype]].[[Prototype]]引用的對象,依次類推,直到[[Prototype]].….[[Prototype]]undefined

Object.prototype[[Prototype]]就是undefined

在控制臺打印仔細(xì)去看:

String.prototype  // ... ...
Obeject.prototype  // ...
Obeject.prototype.prototype // undefined

你還可以在控制臺輸入:

var str = new String("xzavier");
str

然后一層層的查看__proto__,你自己創(chuàng)建的構(gòu)造函數(shù)同此。其實我們的實例沒有繼承到方法和屬性,只是添加了個原型屬性,使用的時候往原型鏈上查找,可以找到父級以及更上一層的原型鏈上的方法,然后使用。

具體參見: 原型鏈

回過頭來,修改Object.prototype就會影響到它的子孫后代。改變Object原型對象會修改到所有通過原型鏈繼承的對象,除非實例的相關(guān)屬性和方法沿原型鏈進(jìn)一步覆蓋。這是一個非常強(qiáng)大的,存在潛在危險的機(jī)制,可以覆蓋或擴(kuò)展對象的行為。

Object.prototype.xxx = function(){ console.log("xxx")};

var str = new String("xzavier");
str.xxx();  // xxx

所以:

Don’t modify objects you don’t own

不過,很多時候我們自己寫代碼,用原型屬性擴(kuò)展方法是非常實用的。

// 數(shù)組去重
Array.prototype.unique = function(){
    return [...new Set(this)];
}
[1,2,3,"4",3,4,3,1,"34",2].unique(); //[1, 2, 3, "4", 4, "34"]
對象的遍歷

數(shù)組是對象,字符串是對象,都可以遍歷。遍歷詳解參考: 流程控制

這兒就說說對象{}類型的遍歷:

for...in 語句可以用來枚舉對象的屬性,為遍歷對象屬性設(shè)計的。

var xzavier = { 
    "name" : "xzavier", 
    "age" : 23,
    "job" : "Jser",
    "width" : 100,
    "height" : 100,
    "border" : 10
};
for (var i in xzavier) { 
    console.log(i);
}
//name age job width height border
for (var i in xzavier) { 
    console.log(xzavier[i]);
}
//xzavier 23 Jser 100 100 10

在設(shè)計對象的時候,鍵值最好是以字符串,而非數(shù)字字符串,如"0", "123",這樣會導(dǎo)致對象重排。
比如:

var obj = {
    "0": 1,
    "abc": 2,
    "def": 3,
    "2": 4,
    "ghi": 5
};

打印obj:

Object {0: 1, 2: 4, abc: 2, def: 3, ghi: 5, __proto__: Object }

用for in 語句輸出:

for (var i in obj) {
  console.log(oo[i]);
}  
// 1 4 2 3 5 

for (var i in obj) {
  console.log(i);
}
// 0 2 abc def ghi

雖然我們平時使用不會受到什么影響,也不會這么設(shè)計。但是你在不在乎,它始終在這里。

react的for循環(huán)key值就建議不要以index為值,也有這個原因,具體不多述。

對象的判斷

我們經(jīng)常會遇到判斷對象類型,這兒就不說typeof了,詳情請參考:數(shù)據(jù)類型判斷

這兒簡寫一下這個不會出錯的方法:

Object.prototype.toString.call("xz"); //"[object String]"
Object.prototype.toString.call(123);  //"[object Number]"
Object.prototype.toString.call(true); //"[object Boolean]"
Object.prototype.toString.call([1,2]); //"[object Array]"
Object.prototype.toString.call({name:"xz"}); //"[object Object]"
Object.prototype.toString.call(function(){}); //"[object Function]"
Object.prototype.toString.call(null); //"[object Null]"
Object.prototype.toString.call(undefined); //"[object Undefined]"
Object.prototype.toString.call(); //"[object Undefined]"
Object.prototype.toString.call(new Date()); //"[object Date]"
Object.prototype.toString.call(/xz/);  //"[object RegExp]"
Object.prototype.toString.call(Symbol()); //"[object Symbol]"

var obj = {name:"Xzavier", age:23};
var a = [1,2,3];

function isType(obj) {
    return Object.prototype.toString.call(obj).slice(8, -1);
}
isType(obj);  // "Object" 
isType(a)  // "Array"  

但是,很多時候我們在處理數(shù)據(jù)的時候,需要判斷一個對象是否為{}:

var isEmptyObject = function(obj) {
    for (var name in obj) {
        return false;
    }
    return true;
};
isEmptyObject({});  // true
isEmptyObject({name: "xzavier"}); //false
對象屬性值訪問

閱讀了溫故js系列(1)- 數(shù)據(jù)類型存儲,我們知道,引用數(shù)據(jù)類型值指保存在堆內(nèi)存中的對象。也就是,變量中保存的實際上的只是一個指針,這個指針指向內(nèi)存中的另一個位置,該位置保存著對象,訪問方式是按引用訪問。

var obj = {
    key: "value",
    name : "xzavier",
    sex : "male",
    "x-v": "xz",
    "xx!": "xxxx",
}; 

在訪問一個對象的一個屬性時,使用.["..."]操作符。obj.keyobj["key"] 都訪問obj中相同的位置,返回值都是"xzavier",所以這兩種方式都在代碼中經(jīng)常使用到。

而這兩種訪問方式的區(qū)別是,.操作符后面需要跟一個標(biāo)識符(Identifier)兼容的屬性名,而["..."]語法基本可以接收任何兼容UTF-8/unicode的字符串作為屬性名。

obj.x-v  // 報錯
obj.xx!  // 報錯
obj["x-v"]  // "xz"
obj["xx!"]  // "xxxx"

因為x-z,xx!不是一個合法的標(biāo)識符屬性名。

["..."] 還可以動態(tài)組建屬性名,這在合適的場景下非常好用。

var obj = {
    number1: "xx",
    number2: "yy",
    number3: "zz"
}
var number = 2;
var select_name = obj["number" + number];  // "yy"
屬性描述符
var xz = {name: "xzavier"}
Object.getOwnPropertyDescriptor( xz, "name" );

正如函數(shù)名,獲取屬性描述符,打印如下:

//  configurable: true,  是否可配置
//  writable: true,   是否可寫
//  value: "xzavier",
//  enumerable: true   是否可枚舉
//  __proto__: Object

我們很少關(guān)注到這些,若有需要,我們關(guān)注的莫過于configurable,writable,enumerable等。
可以通過Object的defineProperty方法修改值的屬性,一般我們使用defineProperty是給對象添加屬性,在這個使用的基礎(chǔ)上,可以對這個值的屬性進(jìn)行配置。

Object.defineProperty( obj, "name", {
    value: "xzavier-1",
    configurable: true,  //是否可配置
    writable: false,   //是否可寫
    enumerable: true   //是否可枚舉
});

obj.name // xzavier-1
obj.name = "xzavier-2" // 不會報錯,但在"use strict"模式下,會報錯TypeError
obj.name // xzavier-1  值沒有被修改

這是writable,接下來說說enumerable,是否可枚舉:

enumerable表述屬性是否能在特定的對象屬性枚舉操作中出現(xiàn),比如在for..in,for...of中遍歷。如果enumerable被設(shè)置為false,那么這個屬性將不會出現(xiàn)在枚舉中,不過它依然可以被屬性訪問方式訪問。

var obj = {
    number1: "xx",
    number2: "yy",
    number3: "zz"
}
Object.defineProperty( obj, "name0", {
    value: "xzavier-1",
    configurable: true,  //是否可配置
    writable: true,   //是否可寫
    enumerable: false   //是否可枚舉
});
for(var i in obj) {
    console.log(i);  // number1 number2 number3  不會出現(xiàn)number0
}
for(var i of keys(obj)) {
    console.log(i);  // number1 number2 number3  不會出現(xiàn)number0
}

再把enumerable設(shè)置為true就可以繼續(xù)在枚舉中遍歷到了。

Object.defineProperty( obj, "name0", {
    enumerable: true   //是否可枚舉
});
for(var i in obj) {
    console.log(i);  // number1 number2 number3 number0
}
for(var i in keys(obj)) {
    console.log(i);  // number1 number2 number3 number0
}

最后說下configurable ,表示屬性是否可以進(jìn)行以上操作,即是否可配置。它是一個單向操作,不可逆。

Object.defineProperty( obj, "name4", {
    value: "xzavier-4",
    configurable: false,  //是否可配置
    writable: false,   //是否可寫
    enumerable: true   //是否可枚舉
}); 

屬性的configurable一旦被設(shè)為false,將不可逆轉(zhuǎn),再用defineProperty設(shè)置屬性將會報錯。

Object.defineProperty( obj, "name4", {
    value: "xzavier-4",
    configurable: true,  //是否可配置
    writable: true,   //是否可寫
    enumerable: true   //是否可枚舉
});
// TypeError
Object方法 Object.assign()

Object.assign(target, ...sources)方法用于從一個或多個源對象的所有可枚舉屬性的值復(fù)制到目標(biāo)對象上,有相同屬性的時候,目標(biāo)對象上的屬性會被覆蓋,最終返回目標(biāo)對象。
接收參數(shù):target目標(biāo)對象,...sources一到多個源對象 不傳則直接返回目標(biāo)對象

我們可以:

1.復(fù)制對象

var obj = { a: 1 };
var obj_1 = Object.assign({}, obj);  // { a: 1 }

2.合并對象

var o1 = { a: 1 };
var o2 = { b: 2 };
var o3 = { c: 3 };

var obj = Object.assign({}, o1, o2, o3);  // { a: 1, b: 2, c: 3 }
Object.create()

Object.create(prototype, descriptors) 方法創(chuàng)建一個具有指定原型且可選擇性地包含指定屬性的對象。接收參數(shù):prototype,必需,要用作原型的對象,可以為 null。descriptors,可選,包含一個或多個屬性描述符的 JavaScript 對象。數(shù)據(jù)屬性描述符包含value,以及 writable,enumerable,configurable,即上面所講。

我們可以:

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

var obj = {
    name: "xzavier"
}

var o = Object.create(obj);
o.name; // "xzavier"

// 但是 name屬性并非o的自定義屬性
o.hasOwnProperty("name"); //false  你在瀏覽器操作之后展開也可以清晰的看到

2.創(chuàng)建一個空對象(沒有原型的對象)
Object.create(null)創(chuàng)建一個擁有空[[Prototype]]鏈接的對象,即這個對象沒有原形鏈。

var obj = Object.create(null);
在控制臺會看到返回 object[ No Properties ]

那這樣的東西創(chuàng)建來又什么用呢,它可以作為一種數(shù)據(jù)存儲方式,不用擔(dān)心它會被原型之類的污染,不用擔(dān)心會有原型鏈查找。它就是一個不會存在一個你意想不到的屬性的存儲結(jié)構(gòu)。所以,可以放心使用它。

3.繼承

function Parent() {}
    
Parent.prototype.say = function() {
    console.info("Hello World");
};

function Childs() {
  Parent.call(this);
}

Childs.prototype = Object.create(Parent.prototype);

var child = new Childs();

child instanceof Childs; //true.
child instanceof Parent; //true.

child.say();  // Hello World
Object.is()

ES6之前,比較兩個值是否相等,使用相等運(yùn)算符(==)和嚴(yán)格相等運(yùn)算符(===)。具體參見:代碼中的哪些判斷。

Object.is()的出現(xiàn)主要是讓以下情況出現(xiàn):

+0 === -0 //true
NaN === NaN // false

Object.is(+0, -0) // false
Object.is(NaN, NaN) // true

Object.is()使用的是嚴(yán)格相等運(yùn)算符(===)做判斷,對+0,-0,NaN做了特殊處理

Object()
Object() // {}
Object({})  // {}
Object(undefined) // {}
Object(null) // {}  
Object(1) // 同 new Number(1)
Object(NaN) // 同 new Number(NaN)
Object("xzavier") // 同 new String("xzavier")
Object(false) // 同 new Boolean(false) 
Object([1,2,3]) // [1,2,3]
Object({name: "xzavier"}) // {name: "xzavier"}
Object(function x(){}) // function x(){}

Object()創(chuàng)造一個“真”對象,返回的都是一個truthy值,是一個對象,所以在if()判斷中都是一個真值。

Object.prototype上的方法

Object.prototype上的方法往往都會被繼承到你實例化的或者字面量形式聲明的數(shù)據(jù)類型中。我們可以直接在實例上使用:

[1,2,3].toString();  //"1,2,3"
({a: 1}).valueOf();  // {a: 1}
......
對象的其他使用

關(guān)于對象的使用,上面所羅列的都是我們經(jīng)常遇到的。我們也經(jīng)常使用對象的特性,做一些事情。

數(shù)組去重:

Array.prototype.unique = function() {
      var arr = [];
      var hash = {};
      for (var i = 0; i < this.length; i++) {
        var item = this[i];
        var key = typeof(item) + item
        if (hash[key] !== 1) {
              arr.push(item);
              hash[key] = 1;
        }
      } 
      return arr;
}
[1,2,3,"4",3,4,3,1,"34",2].unique(); //[1, 2, 3, "4", 4, "34"]

hash去重的核心是構(gòu)建了一個 hash 對象來替代 indexOf。判斷hash的key是否已經(jīng)存在來去重。

最后說一下,文章里面提到的[[Prototype]],__proto__,prototype。

你打印來看,我們只會看到__proto__,所以起作用的是__proto__,__proto__是對象的內(nèi)置屬性,是每個對象都有的屬性,但是這個屬性使用不標(biāo)準(zhǔn),所以不建議直接使用。但是,我們的原型鏈就是基于 __proto__的。通過構(gòu)造函數(shù)得到的實例的 __proto__ 屬性,指向其對應(yīng)的原型對象 String.prototype,這正如文中我們打印 var str = new String("xzavier") 中看到的一樣。

[[Prototype]]是一個隱藏屬性,指向的是這個對象的原型。幾乎每個對象有一個[[prototype]]屬性。

prototype是每個函數(shù)對象都具有的屬性,指向原型對象,如果原型對象被添加屬性和方法,那么由應(yīng)的構(gòu)造函數(shù)創(chuàng)建的實例會繼承prototype上的屬性和方法,這也是我們在代碼中經(jīng)常遇到的。構(gòu)造函數(shù)產(chǎn)生實例時,實例通過其對應(yīng)原型對象的 constructor 訪問對應(yīng)的構(gòu)造函數(shù)對象。所以,我們繼承出來的實例往往沒有constructor,只是通過原型鏈查找,會讓我們產(chǎn)生錯覺,可參見本系列原型鏈文章。

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

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

相關(guān)文章

  • 溫故js系列(9)-相等==&amp;嚴(yán)格相等===&amp;代碼里的那些判斷

    摘要:業(yè)務(wù)越復(fù)雜,邏輯就越復(fù)雜,判斷就越多比較判斷比較判斷是比較兩個值,返回一個布爾值,表示是否滿足比較條件。對于非布爾值的數(shù)據(jù),取反運(yùn)算符會自動將其轉(zhuǎn)為布爾值。 前端學(xué)習(xí):教程&開發(fā)模塊化/規(guī)范化/工程化/優(yōu)化&工具/調(diào)試&值得關(guān)注的博客/Git&面試-前端資源匯總 歡迎提issues斧正:========== JavaScript-判斷 代碼中,多多少少會有判斷語句。業(yè)務(wù)越復(fù)雜,邏輯就越...

    libin19890520 評論0 收藏0
  • 溫故js系列(15)-原型&amp;原型鏈&amp;原型繼承

    摘要:給添加屬性給的原型對象添加屬性原型鏈在中,每個對象都有一個屬性,其保存著的地址就構(gòu)成了對象的原型鏈。實例變量實例函數(shù)原型鏈繼承有了原型鏈,就可以借助原型鏈實現(xiàn)繼承。是中唯一一個處理屬性但是不查找原型鏈的函數(shù)。 前端學(xué)習(xí):教程&開發(fā)模塊化/規(guī)范化/工程化/優(yōu)化&工具/調(diào)試&值得關(guān)注的博客/Git&面試-前端資源匯總 歡迎提issues斧正:原型&原型鏈&原型繼承 JavaScript-原...

    Ethan815 評論0 收藏0
  • 溫故js系列(1)-基本數(shù)據(jù)類型和引用數(shù)據(jù)類型判斷&amp;存儲訪問&amp;類型轉(zhuǎn)換

    摘要:引用數(shù)據(jù)類型引用數(shù)據(jù)類型值指保存在堆內(nèi)存中的對象。訪問方式是按引用訪問。數(shù)據(jù)類型檢測操作符是檢測基本類型的最佳工具。未定義布爾值字符串?dāng)?shù)值對象或函數(shù)用于檢測引用類型,可以檢測到它是什么類型的實例。 前端學(xué)習(xí):教程&開發(fā)模塊化/規(guī)范化/工程化/優(yōu)化&工具/調(diào)試&值得關(guān)注的博客/Git&面試-前端資源匯總 歡迎提issues斧正:數(shù)據(jù)類型 回味,無窮! 數(shù)據(jù)類型定義 數(shù)據(jù)類型分類 基本數(shù)據(jù)...

    jone5679 評論0 收藏0
  • 溫故js系列(14)-閉包&amp;垃圾回收&amp;內(nèi)存泄露&amp;閉包應(yīng)用&amp;作用域鏈&

    摘要:該對象包含了函數(shù)的所有局部變量命名參數(shù)參數(shù)集合以及,然后此對象會被推入作用域鏈的前端。如果整個作用域鏈上都無法找到,則返回。此時的作用域鏈包含了兩個對象的活動對象和對象。 前端學(xué)習(xí):教程&開發(fā)模塊化/規(guī)范化/工程化/優(yōu)化&工具/調(diào)試&值得關(guān)注的博客/Git&面試-前端資源匯總 歡迎提issues斧正:閉包 JavaScript-閉包 閉包(closure)是一個讓人又愛又恨的somet...

    Amio 評論0 收藏0
  • 溫故js系列(12)-ajax&amp;&amp;優(yōu)缺點&amp;&amp;node后端

    摘要:接收響應(yīng)當(dāng)請求發(fā)送到服務(wù)器端,收到響應(yīng)后,響應(yīng)的數(shù)據(jù)會自動填充對象的屬性。一般而已狀態(tài)代碼為作為成功的標(biāo)志。必要時,可以將查詢字符串參數(shù)追加到的末尾,以便提交給服務(wù)器。后端實現(xiàn)可以自學(xué)一點后端知識,便于學(xué)習(xí)。 前端學(xué)習(xí):教程&開發(fā)模塊化/規(guī)范化/工程化/優(yōu)化&工具/調(diào)試&值得關(guān)注的博客/Git&面試-前端資源匯總 歡迎提issues斧正:Ajax JavaScript-Ajax&&no...

    LiangJ 評論0 收藏0

發(fā)表評論

0條評論

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