<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                企業??AI智能體構建引擎,智能編排和調試,一鍵部署,支持知識庫和私有化部署方案 廣告
                [TOC] >[success] # Reflect 使用 ~~~ 1.Object.getOwnPropertyNames(Reflect) 獲取到'Reflect' 上的屬性,因為這些屬性都是 不可枚舉的因此沒有使用'Object.keys' 來獲取,一共獲取了13個靜態方法 ['defineProperty', 'deleteProperty', 'apply', 'construct', 'get', 'getOwnPropertyDescriptor', 'getPrototypeOf', 'has', 'isExtensible', 'ownKeys', 'preventExtensions', 'set', 'setPrototypeOf'] 2.十三個靜態方法具體使用規則 Reflect.apply(target, thisArg, args) Reflect.construct(target, args) Reflect.get(target, name, receiver) Reflect.set(target, name, value, receiver) Reflect.defineProperty(target, name, desc) Reflect.deleteProperty(target, name) Reflect.has(target, name) Reflect.ownKeys(target) Reflect.isExtensible(target) Reflect.preventExtensions(target) Reflect.getOwnPropertyDescriptor(target, name) Reflect.getPrototypeOf(target) Reflect.setPrototypeOf(target, prototype) ~~~ >[danger] ##### 為什么要有Reflect 1. 這是因為在早期的ECMA規范中沒有考慮到這種對 對象本身 的操作如何設計會更加規范,所以將這些API放到了Object上面 2. 是Object作為一個構造函數,這些操作實際上放到它身上并不合適 3. 還包含一些類似于 in、delete操作符,讓JS看起來是會有一些奇怪的 4. 在ES6中新增了Reflect,讓我們這些操作都集中到了Reflect對象上 >[danger] ##### Reflect.apply -- 函數內置插槽 ~~~ 1.Reflect.apply 實際對應'[[call]]' 這個內部插槽,他的用法等同于es5時期'Function.prototype.apply.call', 本意是如果自定義的function 的apply方法被重寫,那么可以采用使用'Function.prototype.apply.call'的形式 來實現自定義function觸發的是未被重寫時候的'apply' 方法,首先需要拆分理解一下'Function.prototype.apply.call' 為什么等同函數自己調用'apply', 'apply(thisArg, [argsArray])' 接受兩個參數分別是'函數運行時使用的 this 值', 和'傳給參數的函數但需要是數組','call' 與之不同點是他'傳給函數參數需要拆分',那此時'Function.prototype.apply' 是一個整體但這個函數需要兩個參數,此時call 傳遞給函數參數位置即確定為apply需要的參數, call('-------' ,指向函數的this,和函數參數數組),此時是'Function.prototype.apply'調用想讓指定到我們自定義函數 此時就需要對call的第一個參數this 去指定call(自定義函數this ,apply指向函數的this,apply函數參數數組) 整體就變成了'自定義函數.apply(apply函數this,參數)' 2.es5 那種繞的寫法,對比'Reflect.apply'做的是同樣事相對就更容易理解 ,'Reflect.apply(target, thisArg, args)' 即'target目標函數','thisArg target函數調用時綁定的this對象','args target函數調用時傳入參數是個數組' 3.如果參數列表為null或undefined,即下面'getName.apply 第二個參數'和'Reflect.apply' 第三個參數,其中 'Reflect.apply' 會報錯,如下。 getName.apply(null, null) // 正常執行 Reflect.apply(getName, null, null) // TypeError 異常 Reflect.apply(getName, null, "") // TypeError 異常 Reflect.apply(getName, null) // TypeError 異常 但目標函數確實沒有參數使用'Reflect.apply' 需要Reflect.apply(getName, null, {})/Reflect.apply(getName, null, []) 來解決 ~~~ * 案例說明 ~~~ const obj = { f: 'w' } var f = 'windows' function getName(age) { console.log(age, this.f) } getName(12) getName.apply(obj, [12]) Reflect.apply(getName, null, [12]) Reflect.apply(getName, obj, [12]) Function.prototype.apply.call(getName, obj, [12]) // 打印結果 12 'windows' 12 'w' 12 'windows' 12 'w' 12 'w' ~~~ >[danger] ##### Reflect.construct -- 函數內置插槽 ~~~ 1.'Reflect.construct(target, argumentsList, [, newTarget])' 1.1.target- 代表目標構造函數的第一個參數 1.2.argumentsList- 第二個參數,代表目標構造函數的參數,類數組格式 1.3.newTarget- 作為新創建對象的原型對象的constructor屬性,可以選不填默認是target。 2.對應的內部插槽'[[constructor]]',等同于'var obj = new Foo(...args)' 3.和'Reflect.apply' 一樣如果不需要對目標函數傳參那么需要傳一個空對象,否則報錯 Reflect.constructor(target, null) // TypeError 異常 Reflect.constructor(target) // TypeError 異常 Reflect.constructor(target, {}) // 不傳參 Reflect.constructor(target, []) // 不傳參 4.案例二可以看出當使用了第三個參數可以改變對象,[[Prototype]] 指向即改變'__proto__',此時創建 出來的對象構造函數指向了第三個參數,等同于之前 // 生成一個對象[[Prototype]] 指向指向OtherClass.prototype var obj2 = Object.create(OtherClass.prototype); // 將target函數this 指向新對象的 OneClass.apply(obj2, args); 只是這種創建其實'OneClass.apply' 激活的是內部插槽'[[Call]]' 只是將this 從windows 指向了我們期望的對象 上,雖然效果一樣但是這種創建的'new.target' 為undefined ~~~ * 案例 ~~~ class A { constructor(age) { this.age = age } getAge() { return this.ages } } const newA = new A(...[10]) // 因為Reflect 第二個參數是偽數組所以為了使用new 更接近使用數組結構 const reflectA = Reflect.construct(A, [10]) ~~~ * 改變生成對象原型鏈指向 ~~~ class A { name = 'a' age = 'b' getAge() {} } class B { zz = 12 getName() {} } const b = Reflect.construct(A, {}, B) console.log(b instanceof A) // false console.log(b instanceof B) // true ~~~ * 如圖 ![](https://img.kancloud.cn/af/4a/af4a435c31a3d8c8ec8f9f60d6a4314e_240x123.png) >[danger] ##### Reflect.defineProperty ~~~ 1.'Reflect.defineProperty(target, propertyKey, attributes)' 使用的內部插槽'[[DefineOwnProperty]]' 1.1.target目標對象。 1.2.propertyKey要定義或修改的屬性的名稱。 1.3.attributes要定義或修改的屬性的描述。 2.等同于'Object.defineProperty(obj, prop, descriptor)',二者不同點Reflect方法返回布爾值 true(成功)/false(失敗) Object返回的是目標對象 ~~~ * 案例 ~~~ function MyDate() { /*…*/ } // 舊寫法 Object.defineProperty(MyDate, 'now', { value: () => Date.now() }); // 新寫法 Reflect.defineProperty(MyDate, 'now', { value: () => Date.now() }); ~~~ >[danger] ##### Reflect.deleteProperty ~~~ 1.對應的內部插槽'[[Delete]]' 方法等同于delete obj[name],用于刪除對象的屬性,方法的第一個參數不是對象,會報錯 'Reflect.deleteProperty(target, propertyKey)' ~~~ ~~~ var obj = { x: 1, y: 2 }; Reflect.deleteProperty(obj, "x"); // true obj; // { y: 2 } var arr = [1, 2, 3, 4, 5]; Reflect.deleteProperty(arr, "3"); // true arr; // [1, 2, 3, , 5] // 如果屬性不存在,返回 true Reflect.deleteProperty({}, "foo"); // true // 如果屬性不可配置,返回 false Reflect.deleteProperty(Object.freeze({foo: 1}), "foo"); // false ~~~ >[danger] ##### Reflect.has ~~~ 1.Reflect.has方法檢查target對象或其原型上的propertyKey屬性是否存在。這與in操作符完全相同。如果找到屬性, 則返回true,否則返回false,對應內部插槽'[[HasProperty]]' ~~~ * 案例 ~~~ 'assign' in Object // true // 新寫法 Reflect.has(Object, 'assign') // true ~~~ >[danger] ##### Reflect.ownKeys ~~~ 1.'Reflect.ownKeys' 使用的內部插槽 '[[OwnPropertyKeys]]' ,方法返回一個由目標對象自身的屬性鍵組成的數組。 它的返回值等同于Object.getOwnPropertyNames(target).concat(Object.getOwnPropertySymbols(target))。 即自身所有屬性(包含可枚舉不可枚舉和symbol 屬性) ~~~ * 案例 ~~~ const sy = Symbol('a') class A { name = 123; [sy] = 145 getName() {} } class B extends A {} const b = new B() // 打印結果 [ 'name', 'sy' ] ~~~ >[danger] ##### Reflect.preventExtensions ~~~ 1.'Reflect.preventExtensions(target)' target 必須是一個對象如果是非對象會異常報錯,對應的內部插 槽'[[PreventExtensions]]',讓對象方法不可以進行擴展,返回一個 Boolean 值表明目標對象是否成功被設置為不可擴展 2.對應的方法,Object.preventExtensions() 方法, 不同點是它對非對象的 target 參數將被強制轉換為對象。 ~~~ * 案例 ~~~ const aa = { name: 1 } Reflect.preventExtensions(aa) aa.age = 1 aa.name = 2 // 打印結果 {name:2} // age 屬性并沒有被添加進去 ~~~ >[danger] ##### Reflect.isExtensible ~~~ 1.'Reflect.isExtensible(target)' target 必須是一個對象如果是非對象會異常報錯,對應的內部插 槽'[[IsExtensible]]',檢查對象是否可以進行擴展,返回一個 Boolean 值表明目標對象是否可擴展 2.對應的方法,Object.isExtensible() 方法, 不同點是它對非對象的 target 參數將被強制轉換為對象。 ~~~ * 案例 ~~~ const aa = { name: 1 } Reflect.preventExtensions(aa) console.log(Reflect.isExtensible(aa)) // false ~~~ >[danger] ##### Reflect.getOwnPropertyDescriptor ~~~ 1.'Reflect.getOwnPropertyDescriptor(target, propertyKey)'trget 必須是一個對象如果是非對象會異常報錯,對應的內部插 槽'[[GetOwnProperty]]',返回屬性的描述符,并且方法返回目標對象的非繼承屬性的屬性描述符即非'[[Prototype]](__proto)' 上的屬性 2.對應的方法,Object.getOwnPropertyDescriptor() 方法, 不同點是它對非對象的 target 參數將被強制轉換為對象。 ~~~ * 案例 ~~~ Reflect.getOwnPropertyDescriptor({x: "hello"}, "x"); // {value: "hello", writable: true, enumerable: true, configurable: true} Reflect.getOwnPropertyDescriptor({x: "hello"}, "y"); // undefined Reflect.getOwnPropertyDescriptor([], "length"); // {value: 0, writable: true, enumerable: false, configurable: false} // ------------------------------ 非繼承屬性 --------------------------------------- const sy = Symbol('a') class A { name = 123; [sy] = 145 getName() {} } class B extends A { getAge() {} } const b = new B() console.log(Reflect.getOwnPropertyDescriptor(b, 'getName')) console.log(Reflect.getOwnPropertyDescriptor(b, 'getAge')) console.log(Reflect.getOwnPropertyDescriptor(b, 'name')) // // 打印結果: // undefined // undefined // { value: 123, writable: true, enumerable: true, configurable: true } ~~~ >[danger] ##### Reflect.getPrototypeOf ~~~ 1.靜態方法 Reflect.getPrototypeOf(target) 與 Object.getPrototypeOf() 方法幾乎是一樣的。都是返回指定對象的原型 (即內部的 [[Prototype]] 屬性的值)。如果目標沒有原型,則返回null。Reflect 要求target 必須是對象,Object則不用 會自動進行拆箱轉換 ~~~ * 案例 ~~~ Reflect.getPrototypeOf( null) // TypeError: Reflect.getPrototypeOf called on non-object Reflect.getPrototypeOf( 'hello') // TypeError: Reflect.getPrototypeOf called on non-object Reflect.getPrototypeOf( {}) // Object {constructor: Object(), __defineGetter__: ?, …} ~~~ >[danger] ##### Reflect.setPrototypeOf ~~~ 1.'Reflect.setPrototypeOf(target, prototype)',返回一個 Boolean 值表明是否原型已經成功設置,內部的 [[Prototype]] 屬性值 對應' Object.setPrototypeOf() ' ~~~ * 案例 ~~~ const object1 = {}; console.log(Reflect.setPrototypeOf(object1, Object.prototype)); // expected output: true console.log(Reflect.setPrototypeOf(object1, null)); // expected output: true const object2 = {}; console.log(Reflect.setPrototypeOf(Object.freeze(object2), null)); // expected output: false ~~~ >[danger] ##### Reflect.get(target, name, receiver) ~~~ 1.'Reflect.get(target, propertyKey, [, receiver])'方法與從 對象 (target[propertyKey]) 中讀取屬性類似,但它是通過一 個函數執行來操作的。如果具有名稱propertyKey的屬性是中的getter函數,則receiver參數則被當做 this。 如果缺少receiver,則this是target,注意案例二這類改變this 只能是getter函數的 2.調用 reflect.get() 類似于 target[propertykey] 表達式,因為它也搜索 target 原型上的屬性值。如果目標上不存在屬性, 則返回 undefined。 ~~~ * 案例 1 ~~~ var computer1 = { processor: "Intel", brand: "Dell", operatingSystem: "windows 7" }; console.log(computer1); Reflect.get(computer1, "processor"); // computer1.processor 等同 console.log(computer1.processor); ~~~ * 案例二 ~~~ const dinoComputer = { processor: "Intel", brand: "Dell", operatingSystem: "windows 7" }; Reflect.defineProperty(dinoComputer, "computerDetails", { get: function() { return new String().concat(`*********Computer Details********\r\n`, `****Processor: ${this.processor}***********\r\n`, `****Brand: ${this.brand}*****************\r\n`, `****Operating System: ${this.operatingSystem}*\r\n`); } }); console.log(dinoComputer); let oldComputer = Reflect.get(dinoComputer, "computerDetails", { processor: "AMD K62", brand: "Clone", operatingSystem: "Windows XP" }); console.log(oldComputer); ~~~ >[danger] ##### Reflect.set ~~~ 1.'Reflect.set(target, propertyKey, value[, receiver])' 等同于'target[propertyKey] = value' ~~~ >[info] ## 參考文章 [JavaScript Reflection and Reflect API ](https://www.codeproject.com/Articles/5275933/JavaScript-Reflection-and-Reflect-API#get) [【譯】JavaScript元編程之——Reflect API簡介 ](https://juejin.cn/post/7060056954130923528#heading-17) [Metaprogramming in ES6: Part 2 - Reflect](https://www.keithcirkel.co.uk/metaprogramming-in-es6-part-2-reflect/)
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看