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

資訊專欄INFORMATION COLUMN

JS之對象(2)

CarterLi / 510人閱讀

摘要:前言一篇徹底搞懂對象從此不用擔心沒對象啦本文從對象定義方法對象屬性數據類型遍歷幾種方法對象拷貝和攔截對象屬性方法及代碼實現幾個方面由淺入深介紹對象對象的聲明方法字面量構造函數的作用創了一個新對象指向構造函數構造函數有返回會替換出來的對象如果

前言
一篇徹底搞懂對象,從此不用擔心沒對象啦;
本文從對象定義方法,對象屬性,Symbol數據類型,遍歷幾種方法,對象拷貝,vue2.x和vue3.x攔截對象屬性方法及代碼實現幾個方面由淺入深介紹對象
1.對象的聲明方法 1.1 字面量
var test2 = {x:123,y:345};
console.log(test2);//{x:123,y:345};
console.log(test2.x);//123
console.log(test2.__proto__.x);//undefined
console.log(test2.__proto__.x === test2.x);//false
1.2 構造函數
var test1 = new Object({x:123,y:345});
console.log(test1);//{x:123,y:345}
console.log(test1.x);//123
console.log(test1.__proto__.x);//undefined
console.log(test1.__proto__.x === test1.x);//false

new的作用:
1.創了一個新對象;
2.this指向構造函數;
3.構造函數有返回,會替換new出來的對象,如果沒有就是new出來的對象

1.3 內置方法

Obejct.create(obj,descriptor),obj是對象,describe描述符屬性(可選)

let test = Object.create({x:123,y:345});
console.log(test);//{}
console.log(test.x);//123
console.log(test.__proto__.x);//3
console.log(test.__proto__.x === test.x);//true
1.4 三種方法的優缺點

1.功能:都能實現對象的聲明,并能夠賦值和取值
2.繼承性:內置方法創建的對象繼承到__proto__屬性上
3.隱藏屬性:三種聲明方法會默認為內部的每個成員(屬性或方法)生成一些隱藏屬性,這些隱藏屬性是可以讀取和可配置的,屬性分類見下面
4.屬性讀取:Object.getOwnPropertyDescriptor()或getOwnPropertyDescriptor()
5.屬性設置:Object.definePropertype或Object.defineProperties

2.對象的屬性 2.1 屬性分類

1.數據屬性4個特性:
configurable(可配置),enumerable(可枚舉),writable(可修改),value(屬性值)

2.訪問器屬性2個特性:
get(獲取),set(設置)

3.內部屬性
由JavaScript引擎內部使用的屬性;
不能直接訪問,但是可以通過對象內置方法間接訪問,如:[[Prototype]]可以通過 Object.getPrototypeOf()訪問;
內部屬性用[[]]包圍表示,是一個抽象操作,沒有對應字符串類型的屬性名,如[[Prototype]].

2.2 屬性描述符

1.定義:將一個屬性的所有特性編碼成一個對象返回
2.描述符的屬性有:數據屬性和訪問器屬性
3.使用范圍:
作為方法Object.defineProperty, Object.getOwnPropertyDescriptor, Object.create的第二個參數,

2.3 屬性描述符的默認值

1.訪問對象存在的屬性

特性名 默認值
value 對應屬性值
get 對應屬性值
set undefined
writable true
enumerable true
configurable true

所以通過上面三種聲明方法已存在的屬性都是有這些默認描述符
2.訪問對象不存在的屬性

特性名 默認值
value undefined
get undefined
set undefined
writable false
enumerable false
configurable false
2.3 描述符屬性的使用規則

get,set與wriable,value是互斥的,如果有交集設置會報錯

2.4 屬性定義

1.定義屬性的函數有兩個:Object.defineProperty和Object.defineProperties.例如:
Object.defineProperty(obj, propName, desc)

2.在引擎內部,會轉換成這樣的方法調用:
obj.[[DefineOwnProperty]](propName, desc, true)

2.5 屬性賦值

1.賦值運算符(=)就是在調用[[Put]].比如:
obj.prop = v;

2.在引擎內部,會轉換成這樣的方法調用:
obj.[[Put]]("prop", v, isStrictModeOn)

2.6 判斷對象的屬性
名稱 含義 用法
in 如果指定的屬性在指定的對象或其原型鏈中,則in 運算符返回true "name" in test //true
hasOwnProperty() 只判斷自身屬性 test.hasOwnProperty("name") //true
.或[] 對象或原型鏈上不存在該屬性,則會返回undefined test.name //"lei" test["name"] //"lei"
3.Symbol 3.1概念

是一種數據類型;
不能new,因為Symbol是一個原始類型的值,不是對象。

3.2 定義方法

Symbol(),可以傳參

var s1 = Symbol();
var s2 = Symbol();
s1 === s2 // false

// 有參數的情況
var s1 = Symbol("foo");
var s2 = Symbol("foo");
s1 === s2 // false
3.3 用法

1.不能與其他類型的值進行運算;
2.作為屬性名

let mySymbol = Symbol();

// 第一種寫法
var a = {};
a[mySymbol] = "Hello!";

// 第二種寫法
var a = {
  [mySymbol]: "Hello!"
};

// 第三種寫法
var a = {};
Object.defineProperty(a, mySymbol, { value: "Hello!" });

// 以上寫法都得到同樣結果
a[mySymbol] // "Hello!"

3.作為對象屬性名時,不能用點運算符,可以用[]

let a = {};
let name = Symbol();
a.name = "lili";
a[name] = "lucy";
console.log(a.name,a[name]); 

4.遍歷不會被for...in、for...of和Object.keys()、Object.getOwnPropertyNames()取到該屬性

3.4 Symbol.for

1.定義:在全局中搜索有沒有以該參數作為名稱的Symbol值,如果有,就返回這個Symbol值,否則就新建并返回一個以該字符串為名稱的Symbol值
2.舉例:

var s1 = Symbol.for("foo");
var s2 = Symbol.for("foo");
s1 === s2 // true
3.5 Symbol.keyFor

1.定義:返回一個已登記的Symbol類型值的key
2.舉例:

var s1 = Symbol.for("foo");
Symbol.keyFor(s1) // "foo"

var s2 = Symbol("foo");
Symbol.keyFor(s2) // undefined 
4.遍歷 4.1 一級對象遍歷方法
方法 特性
for ... in 遍歷對象自身的和繼承的可枚舉屬性(不含Symbol屬性)
Object.keys(obj) 返回一個數組,包括對象自身的(不含繼承的)所有可枚舉屬性(不含Symbol屬性)
Object.getOwnPropertyNames(obj) 返回一個數組,包括對象自身的所有可枚舉屬性(不含Symbol屬性)
Object.getOwnPropertySymbols(obj) 返回一個數組,包含對象自身的所有Symbol屬性
Reflect.ownKeys(obj) 返回一個數組,包含對象自身的所有(不枚舉、可枚舉和Symbol)屬性
Reflect.enumerate(obj) 返回一個Iterator對象,遍歷對象自身的和繼承的所有可枚舉屬性(不含Symbol屬性)

總結:1.只有Object.getOwnPropertySymbols(obj)和Reflect.ownKeys(obj)可以拿到Symbol屬性
2.只有Reflect.ownKeys(obj)可以拿到不可枚舉屬性

4.2 多級對象遍歷

數據模型:

var treeNodes = [
    {
     id: 1,
     name: "1",
     children: [
       {
        id: 11,
        name: "11",
        children: [
         {
          id: 111,
          name: "111",
          children:[]
          },
          {
            id: 112,
            name: "112"
           }
          ]
         },
         {
          id: 12,
          name: "12",
          children: []
         }
         ],
         users: []
        },
      ];

遞歸:

var parseTreeJson = function(treeNodes){
      if (!treeNodes || !treeNodes.length) return;

       for (var i = 0, len = treeNodes.length; i < len; i++) {

            var childs = treeNodes[i].children;

            console.log(treeNodes[i].id);

            if(childs && childs.length > 0){
                 parseTreeJson(childs);
            }
       }
    };

    console.log("------------- 遞歸實現 ------------------");
    parseTreeJson(treeNodes);
5.深度拷貝 5.1 Object.assign

1.定義:將源對象(source)的所有可枚舉屬性,復制到目標對象(target)
2.用法:

合并多個對象
var target = { a: 1, b: 1 };
var source1 = { b: 2, c: 2 };
var source2 = { c: 3 };
Object.assign(target, source1, source2);

3.注意:
這個是偽深度拷貝,只能拷貝第一層

5.2 JSON.stringify

1.原理:是將對象轉化為字符串,而字符串是簡單數據類型

5.3 遞歸拷貝
function deepClone(source){
  const targetObj = source.constructor === Array ? [] : {}; // 判斷復制的目標是數組還是對象
  for(let keys in source){ // 遍歷目標
    if(source.hasOwnProperty(keys)){
      if(source[keys] && typeof source[keys] === "object"){ // 如果值是對象,就遞歸一下
        targetObj[keys] = source[keys].constructor === Array ? [] : {};
        targetObj[keys] = deepClone(source[keys]);
      }else{ // 如果不是,就直接賦值
        targetObj[keys] = source[keys];
      }
    }
  }
  return targetObj;
}  


6.數據攔截

定義:利用對象內置方法,設置屬性,進而改變對象的屬性值

6.1 Object.defineProterty

1.ES5出來的方法;
2.三個參數:對象(必填),屬性值(必填),描述符(可選);
3.defineProterty的描述符屬性

數據屬性:value,writable,configurable,enumerable
訪問器屬性:get,set
注:不能同時設置value和writable,這兩對屬性是互斥的

4.攔截對象的兩種情況:

let obj = {name:"",age:"",sex:""  },
    defaultName = ["這是姓名默認值1","這是年齡默認值1","這是性別默認值1"];
  Object.keys(obj).forEach(key => {
    Object.defineProperty(obj, key, {
      get() {
        return defaultName;
      },
      set(value) {
        defaultName = value;
      }
    });
  });

  console.log(obj.name);
  console.log(obj.age);
  console.log(obj.sex);
  obj.name = "這是改變值1";
  console.log(obj.name);
  console.log(obj.age);
  console.log(obj.sex);

  let objOne={},defaultNameOne="這是默認值2";
  Object.defineProperty(obj, "name", {
      get() {
        return defaultNameOne;
      },
      set(value) {
        defaultNameOne = value;
      }
  });
  console.log(objOne.name);
  objOne.name = "這是改變值2";
  console.log(objOne.name);

5.攔截數組變化的情況

let a={};
bValue=1;
Object.defineProperty(a,"b",{
    set:function(value){
        bValue=value;
        console.log("setted");
    },
    get:function(){
        return bValue;
    }
});
a.b;//1
a.b=[];//setted
a.b=[1,2,3];//setted
a.b[1]=10;//無輸出
a.b.push(4);//無輸出
a.b.length=5;//無輸出
a.b;//[1,10,3,4,undefined];

結論:defineProperty無法檢測數組索引賦值,改變數組長度的變化;
    但是通過數組方法來操作可以檢測到


6.存在的問題

不能監聽數組索引賦值和改變長度的變化
必須深層遍歷嵌套的對象,因為defineProterty只能劫持對象的屬性,因此我們需要對每個對象的每個屬性進行遍歷,如果屬性值也是對象那么需要深度遍歷,顯然能劫持一個完整的對象是更好的選擇

6.2 proxy

1.ES6出來的方法,實質是對對象做了一個攔截,并提供了13個處理方法
13個方法詳情請戳,阮一峰的proxy介紹

2.兩個參數:對象和行為函數

let handler = {
    get(target, key, receiver) {
      console.log("get", key);
      return Reflect.get(target, key, receiver);
    },
    set(target, key, value, receiver) {
      console.log("set", key, value);
      return Reflect.set(target, key, value, receiver);
    }
  };
  let proxy = new Proxy(obj, handler);
  proxy.name = "李四";
  proxy.age = 24;

3.問題和優點
reflect對象沒有構造函數
可以監聽數組索引賦值,改變數組長度的變化,
是直接監聽對象的變化,不用深層遍歷

6.3 defineProterty和proxy的對比

1.defineProterty是es5的標準,proxy是es6的標準;

2.proxy可以監聽到數組索引賦值,改變數組長度的變化;

3.proxy是監聽對象,不用深層遍歷,defineProterty是監聽屬性;

3.利用defineProterty實現雙向數據綁定(vue2.x采用的核心)
請戳,剖析Vue原理&實現雙向綁定MVVM
4.利用proxy實現雙向數據綁定(vue3.x會采用)

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

轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/102133.html

相關文章

  • JS修仙一界本源

    摘要:時間一晃就是數月,齊云早已把界基本情況了解了,不過至于三座大山里隱藏的謎團卻遲遲沒有頭緒。它是界本源之一。事實上,根本沒有構造函數,或者人人都是構造函數。所以,明白這個界的一界本源,才能在這里暢游天地之間。 自計算機宇宙誕生以來,有很多大神通者在這里開天辟地,開創了很多界,有C、C++、Java等世界,它們彼此相連,其中有一處叫做JavaScript的世界,自被開辟以來吸引了很多修行者...

    I_Am 評論0 收藏0
  • JS面向對象二 【原型鏈】(對象對象間的關系)

    摘要:面向對象之二原型鏈對象和對象之間的關系注意這個系列文章要經常站在之父的視角去思考。思考問題我們都知道都屬于那么既然他們都是對象一定有某些相同之處吧對象和對象之間有什么關聯呢如果說你沒有思考過這個問題那么可以換一個更具體的問題。 JS面向對象之二 【原型鏈】(對象和對象之間的關系) 注意這個系列文章,要經常站在JS之父的視角去思考。 牢記我們的需求,我要在JS沒有class的情況下,那么...

    Jochen 評論0 收藏0
  • JS面向對象三【this】 (對象和函數間的關系)

    摘要:實際上就是做了這樣一件事情顯式的指定是回顧一下隱式模式顯示模式觀點里所有函數都接受個參數第一個第二個是函數被調用時一定會有這個參數如果你用調用函數就是顯式的傳遞和如果你用語法直接調用函數那就去幫你偷偷的傳遞。 JS面向對象之三【this】 (對象和函數之間的關系) 上一篇,談了對象和對象的關系,現在我們談談對象和函數的關系 先說結論,也就是觀點1 觀點1: JS里函數和對象沒有關系,J...

    roland_reed 評論0 收藏0
  • JS14種設計模式 (6)

    摘要:序列文章面試之函數面試之對象面試之數組的幾個不操作面試之對比分析面試之數據結構與算法前言設計模式如果應用到項目中,可以實現代碼的復用和解耦,提高代碼質量。 showImg(https://segmentfault.com/img/bVbq2VA?w=480&h=260); 序列文章 JS面試之函數(1)JS面試之對象(2)JS面試之數組的幾個不low操作(3)JS面試之http0.9~...

    luckyyulin 評論0 收藏0
  • 好程序員Web前端培訓入門JS基礎知識梳理匯總

    摘要:好程序員前端培訓入門之基礎知識梳理匯總,前端工程師是當前各大企業都比較稀缺的人才,薪資待遇和就業前景都很不錯。作用域鏈的前端,始終是當前執行代碼所在環境的變量對象。   好程序員Web前端培訓入門之JS基礎知識梳理匯總,Web前端工程師是當前各大企業都比較稀缺的人才,薪資待遇和就業前景都很不錯。不論是專業還是非專業,有基礎亦或是無基礎,都想通過學習Web前端實現高薪就業。不過,學習要一...

    int64 評論0 收藏0
  • 好程序員Web前端培訓入門JS基礎知識梳理匯總

    摘要:好程序員前端培訓入門之基礎知識梳理匯總,前端工程師是當前各大企業都比較稀缺的人才,薪資待遇和就業前景都很不錯。作用域鏈的前端,始終是當前執行代碼所在環境的變量對象。   好程序員Web前端培訓入門之JS基礎知識梳理匯總,Web前端工程師是當前各大企業都比較稀缺的人才,薪資待遇和就業前景都很不錯。不論是專業還是非專業,有基礎亦或是無基礎,都想通過學習Web前端實現高薪就業。不過,學習要一...

    kviccn 評論0 收藏0

發表評論

0條評論

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