Heim  >  Artikel  >  Web-Frontend  >  Neue Funktionen von ES6: Detaillierte Erläuterung des Reflect-Objektcodes in JavaScript

Neue Funktionen von ES6: Detaillierte Erläuterung des Reflect-Objektcodes in JavaScript

黄舟
黄舟Original
2017-03-07 14:24:121586Durchsuche

Einführung in Reflect:

Das Reflect-Objekt wurde in meinem Knoten (v4.4.3) nicht implementiert, ebenso wenig wie Babel (6.7.7). Ja, ff unterstützt Proxy und Reflect seit langem. Wenn Sie möchten, dass Node Reflect unterstützt, können Sie Harmony-Reflect installieren über Reflect.method(). Die Methoden von Reflect ähneln denen von Proxy, und die meisten nativen Object Reflect-Methoden wurden neu implementiert.

Warum Reflect verwenden

Hier sind einige Gründe, warum Sie Reflect verwenden sollten. Übersetzungsadresse: Reflect, grob übersetzt:

1: Weitere nützliche Rückgabewerte: Reflect hat einige Methoden, die mit den Object-Methoden in ES5 identisch sind, wie zum Beispiel: Reflect.getOwnPropertyDescriptor und Reflect.defineProperty. Wenn Object.defineProperty(obj, name, desc) jedoch erfolgreich ausgeführt wird, werden obj sowie verursachte Fehler zurückgegeben aus anderen Gründen. Reflect .defineProperty gibt nur false oder true zurück, um anzugeben, ob die Eigenschaft des Objekts festgelegt ist:

Umgestaltet wie folgt:
try {
  Object.defineProperty(obj, name, desc);
  // property defined successfully
} catch (e) {
  // possible failure (and might accidentally catch the wrong exception)
}

Die restlichen Methoden, zum Beispiel Reflect.set, Reflect.deleteProperty, Reflect.preventExtensions, Reflect.setPrototypeOf, können alle umgestaltet werden.
if (Reflect.defineProperty(obj, name, desc)) {
  // success
} else {
  // failure
}

2: Funktionsoperation, wenn Sie feststellen möchten, ob ein Objekt vorhanden ist hat eine Definition oder erbt den Attributnamen, in ES5 Beurteilen Sie so: name in obj; oder löschen Sie ein Attribut: delete obj[name] Obwohl diese einfach zu verwenden, sehr kurz und sehr klar sind, müssen sie in a gekapselt werden Klasse bei Verwendung;

Es gibt Reflect, es kapselt es für Sie, Reflect.has(obj, name), Reflect.deleteProperty(obj, name);

3: Eine zuverlässigere Funktion Ausführungsmethode: In ES müssen Sie eine Funktion f ausführen und ihr einen Satz Parameterargumente übergeben. Wenn Sie dies binden möchten, müssen Sie es wie folgt schreiben:

Aber f's gelten kann als eigene Anwendung des Benutzers neu definiert werden, daher ist es immer noch so. Es ist zuverlässiger zu schreiben:
f.apply(obj, args)

Der obige Code ist zu lang und schwer zu verstehen. Mit Reflect können wir ihn kürzer machen. prägnanter und klarer:
Function.prototype.apply.call(f, obj, args)

4: Konstruktor in Form variabler Parameter: Stellen Sie sich vor, Sie möchten einen Konstruktor mit Parametern unbestimmter Länge instanziieren. In ES5 können wir Erweiterungssymbole verwenden so geschrieben:
Reflect.apply(f, obj, args)

Aber in ES5 werden Erweiterungszeichen nicht unterstützt, daher können wir nur F.apply oder F.call verwenden, um andere Parameter zu übergeben. Leider ist F ein Konstruktor ist ein Betrug. Aber mit Reflect sind wir in ES5. Es kann so geschrieben werden:
var obj = new F(...args)

5: Dies steuert den Accessor oder Reader: In ES5, wenn Sie die Attribute eines Elements lesen möchten oder die Attribute festlegen, müssen Sie Folgendes tun:
var obj = Reflect.construct(F, args)

Die Methoden Reflect.get und Reflect.set ermöglichen es uns, dasselbe zu tun, und sie fügen einen zusätzlichen Parameterempfänger hinzu, der es uns ermöglicht, das festzulegen Setter- und Getter-Kontext des Objekts:
var name = ... // get property name as a string
obj[name] // generic property lookup
obj[name] = value // generic property update

Zugriff Der Container möchte keine eigene Methode verwenden, sondern diese an den Wrapper umleiten:
var name = ... // get property name as a string
Reflect.get(obj, name, wrapper) // if obj[name] is an accessor, it gets run with `this === wrapper`
Reflect.set(obj, name, value, wrapper)

6: Direkten Zugriff vermeiden zu __proto__: ES5 stellt Object.getPrototypeOf(obj) bereit, um auf den Prototyp des Objekts zuzugreifen, ES6 bietet außerdem
var obj = {
    set foo(value) { return this.bar(); },
    bar: function() {
        alert(1);
    }
};
var wrapper = {
    bar : function() {
        console.log("wrapper");
    }
}
Reflect.set(obj, "foo", "value", wrapper);
und Reflect.setPrototypeOf(obj, newProto). Dies ist eine neue Methode, um auf den Prototyp eines Objekts zuzugreifen und ihn festzulegen:

Reflect.getPrototypeOf(obj)Verwendung von Reflect.apply

Reflect .apply ist eigentlich der Ersatz für Function.prototype.apply() in ES5. Zur Ausführung von Reflect.apply

Der erste Parameter ist: Die Funktion, die ausgeführt werden muss;

Der zweite Parameter ist: Der Kontext, der zum Ausführen der Funktion verwendet werden muss

Der dritte Parameter ist: Es ist ein Array oder Pseudo- Array, das als Parameter zum Ausführen der Funktion verwendet wird;



<script>
let fn = function() {
    this.attr = [0,1,2,3];
};
let obj = {};
Reflect.apply(fn, obj, [])
console.log(obj);  
</script>

DEMO von Reflect.apply:

Reflect kann in Verbindung mit Proxy verwendet werden:
<script>
Reflect.apply(Math.floor, undefined, [1.75]); // 输出:1;
Reflect.apply(String.fromCharCode, undefined, [104, 101, 108, 108, 111]); // 输出:"hello"
Reflect.apply(RegExp.prototype.exec, /ab/, ["confabulation"]).index; //输出: 4
Reflect.apply("".charAt, "ponies", [3]); // 输出:"i"
</script>

Reflect.construct() Verwendung:
{
    var  Fn = function(){
    };
    Fn.prototype.run = function() {
        console.log( "runs out" );
    };
    var ProxyFn  = new Proxy(Fn, {
        construct (target ,arugments) {
            console.log("proxy constructor");
            var obj = new target(...arugments);
            //Reflect.apply的使用方法;
            Reflect.apply(target.prototype.run, obj, arugments);
            return obj;
        }
    });
    new ProxyFn ();  //会先输出: "proxy constructor" ; 再输出: runs out
}

Reflect.construct ist Eigentlich ist es ein Instanziierungskonstruktor. Die Ausführungsmethode ist unterschiedlich, aber der Effekt ist derselbe. Der erste Parameter des Konstruktors ist der Konstruktor Pseudo-Arrays, die aus Parametern bestehen, sind:

Reflect.consturct ist also zumindest bisher dasselbe wie der neue Konstruktor.

var Fn = function(arg) {
    this.args = [arg]
};
console.log( new Fn(1), Reflect.construct(Fn,[1]) ); // 输出是一样的

var d = Reflect.construct(Date, [1776, 6, 4]);
d instanceof Date; // true
d.getFullYear(); // 1776
//所以Reflect.consturct和new 构
Wir können das übergeben Dritter Parameter für Reflect.construct. Das neue Element wird diese Superklasse erben Array, erbt das Array, verfügt aber auch über eigene Methoden;

Verwendung von Reflect.defineProperty;
<script>
function someConstructor() {}
var result = Reflect.construct(Array, [], someConstructor);
Reflect.getPrototypeOf(result); // someConstructor.prototype
Array.isArray(result); // true
//or
var Fn = function() {
    this.attr = [1];
};
var Person = function() {
};
Person.prototype.run = function() {
};
console.log( Reflect.construct(Fn, [], Person) );
</script>

Reflect.defineProperty gibt einen booleschen Wert zurück und fügt Attribute hinzu und Attributwerte zum Objekt durch direkte Zuweisung geben ein gesamtes Objekt zurück. Wenn das Hinzufügen fehlschlägt, wird ein Fehler ausgegeben.

Verwenden Sie Reflect.defineProperty, um Werte hinzuzufügen
<script>
var obj = {};
if( Reflect.defineProperty(obj, "x", {value : 7 }) ) {
    console.log("added success");
}else{
    console.log("添加失败");
};
</script>

如果我们执行preventExtensions, 通过Object.defindProperty定义新属性报错了, 但是通过Reflect.defineProperty没有报错, 返回了一个false的值:

var obj = {};
Object.preventExtensions(obj);
Object.defineProperty(obj, "x" , {
    value: 101,
    writable: false,
    enumerable: false,
    configurable: false
});// 直接抛错了;
console.log( Reflect.defineProperty(obj, "x", {value:101}) ) //返回false:

如果通过直接赋值的方式, 无论是否正确赋值, 都返回设置的值, 除非我们手动确认对象的属性值是否设置成功;

<script>
var obj = {};
Object.preventExtensions(obj);
console.log( obj.aa = 1 ); //输出:1;
console.log(obj.aa) //输出:undefined;
</script>

Reflect.deleteProperty的使用:

Reflect.deleteProperty和Reflect.defineProperty的使用方法差不多, Reflect.deleteProperty和 delete obj.xx的操作结果是一样, 区别是使用形式不同:一个是操作符,一个是函数调用;

Reflect.deleteProperty(Object.freeze({foo: 1}), "foo"); // false
delete Object.freeze({foo: 1}).foo; //输出:false;

Reflect.get()方法的使用

这个方法的有两个必须的参数: 第一个为obj目标对象, 第二个为属性名对象, 第三个是可选的,是作为读取器的上下文(this);

var obj = {};
obj.foo = 1;
console.log( obj.foo ); //输出:1;
console.log( Reflect.get(obj, "foo") ) //输出:1;

如果Reflect.get有第三个参数的话, 第三个参数会作为读取器的上下文:

var Reflect = require(&#39;harmony-reflect&#39;);

var obj = {
    "foo" : 1,
    get bar() {
        return this.foo;
    }
};
var foo = {};
foo.foo = "heheda";
console.log(Reflect.get(obj, "bar", foo));

Reflect.getOwnPropertyDescritptor()方法的使用:

通过Reflect.getOwnPropertyDescritptor获取属性描述:

Reflect.getOwnPropertyDescriptor({x: "hello"}, "x");
//也可以这样获取:
Object.getOwnPropertyDescriptor({x:"1"},"x");
//这两个的区别是一个会包装对象, 一个不会:
Reflect.getOwnPropertyDescriptor("hello",0); //抛出异常
Object.getOwnPropertyDescriptor("hello",0); //输出: {value: "h", writable: false, enumerable: true, configurable: false}

Reflect.getPrototypeOf()方法的使用:

Reflect.getPrototypeOf和Object.getPrototypeOf是一样的, 他们都是返回一个对象的原型

Reflect.getPrototypeOf({}); // 输出:Object.prototype
Reflect.getPrototypeOf(Object.prototype); // 输出:null
Reflect.getPrototypeOf(Object.create(null)); // 输出: null

Reflect.has的使用

Reflect.has这个方法有点像操作符:in , 比如这样: xx in obj;

<script>
Reflect.has({x:0}, "x") //输出: true;
Reflect.has({y:0}, "y") //输出:true
; var obj = {x:0}; console.log( "x" in obj); 
var proxy = new Proxy(obj, { has : function(target, args) { console.log("执行has方法"); 
return Reflect.has(target,...args); } }); 
console.log( "x" in proxy); //输出:true; console.log(Reflect.has(proxy, "x")) //输出:true; </script>


这个demo的obj相当于变成了一个方法了, 没他什么用 , 只是利用了他的has方法:

obj = new Proxy({}, {
    has(t, k) { return k.startsWith("door"); }
});
Reflect.has(obj, "doorbell"); // true
Reflect.has(obj, "dormitory"); // false

Reflect.isExtensible()的使用

// 现在这个元素是可以扩展的;
var empty = {};
Reflect.isExtensible(empty); // === true

// 使用preventExtensions方法, 让这个对象无法扩展新属性;
Reflect.preventExtensions(empty);
Reflect.isExtensible(empty); // === false

// 这个对象无法扩展新属性, 可写的属性依然可以改动
var sealed = Object.seal({});
Reflect.isExtensible(sealed); // === false

// 这个对象完全被冻结了
var frozen = Object.freeze({});
Reflect.isExtensible(frozen); // === false

Reflect.isExtensible和Object.isExtensible的区别是, 如果参数不对,一个会抛错, 另一个只是返回true或者false:

Reflect.isExtensible(1);
// 抛错了: 1 is not an object
Object.isExtensible(1);
// 返回false;

Reflect.ownKeys()方法的使用:

Reflect.ownKeys, Object可没有ownKeys方法, Reflect.ownKeysz他的作用是返回对象的keys;

console.log(Reflect.ownKeys({"a":0,"b":1,"c":2,"d":3})); //输出 :["a", "b", "c", "d"]
console.log(Reflect.ownKeys([])); // ["length"]
var sym = Symbol.for("comet");
var sym2 = Symbol.for("meteor");
var obj = {[sym]: 0, "str": 0, "773": 0, "0": 0,
    [sym2]: 0, "-1": 0, "8": 0, "second str": 0};
Reflect.ownKeys(obj); //输出:/ [ "0", "8", "773", "str", "-1", "second str", Symbol(comet), Symbol(meteor) ]

Reflect.ownKeys的排序是根据: 先显示数字, 数字根据大小排序,然后是 字符串根据插入的顺序排序, 最后是symbol类型的key也根据插入插入顺序排序;

出现这中排序是因为,你给一个对象属性赋值时候, 对象的key的排序规则就是先数字, 在字符串, 最后是symbol类型的数据;

Reflect.preventExtensions()的使用方法:

Object也有preventExtensions方法, 和Reflect.preventExtensions()有一点区别, 如果Reflect.preventExtensions参数不是对象会抛错;

var empty = {};
Reflect.isExtensible(empty); // === true

// 执行preventExtensions后的对象可以修改;
Reflect.preventExtensions(empty);
Reflect.isExtensible(empty); // === false

Reflect.preventExtensions(1);
// TypeError: 1 is not an object
Object.preventExtensions(1);
//不会抛错, 会返回:1

Reflect.set()

Reflect.set方法和get是差不多的;

var obj = {};
Reflect.set(obj, "prop", "value"); // 输出:true
console.log( obj.prop ); // 输出:"value"

var arr = ["duck", "duck", "duck"];
Reflect.set(arr, 2, "goose"); // true
console.log( arr[2] ); // "goose"

Reflect.set(arr, "length", 1); // true
console.log( arr );// ["duck"];

Reflect.set(obj)相当于 Reflect.set(obj, undefined, undefined);

var obj = {};
Reflect.set(obj); // 输出:true
//以上的代码相当于 Reflect.set(obj, undefined, undefined);
Reflect.getOwnPropertyDescriptor(obj, "undefined");
// { value: undefined, writable: true, enumerable: true, configurable: true }

Reflect.set也可以有第四个参数, 这个参数会作为stter的this;

var obj = {
    value : 10,
    set key( value ) {
        console.log("setter");
        this.value =  value;
    },
    get key() {
        return this.value;
    }
};
Reflect.set(obj,"key","heheda", obj);
console.log(obj);

Reflect.setPrototypeOf()

Reflect.setPrototypeOf()方法和Object.setPrototypeOf差不多一样样的, 会给对象设置原型, 就是更改对象的__proto__属性了…;

Reflect.setPrototypeOf({}, Object.prototype); // 输出true

// 给该对象数组[[Prototype]] 为null.
Reflect.setPrototypeOf({}, null); // true
// 此时的obj.__proto__为undefine

//把对象冻结以后重新设置[[prototype]]
Reflect.setPrototypeOf(Object.freeze({}), null); // false

// 如果原型链循环依赖的话就会返回false.
var target = {};
var proto = Object.create(target);
Reflect.setPrototypeOf(target, proto); // false

 以上就是ES6新特性:JavaScript中的Reflect对象代码详解的内容,更多相关内容请关注PHP中文网(www.php.cn)!



Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn