前端开发者进阶之ECMAScript新特性--Object.create

Posted 小易的博客

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了前端开发者进阶之ECMAScript新特性--Object.create相关的知识,希望对你有一定的参考价值。

前端开发者进阶之ECMAScript新特性【一】--Object.create

 

Object.create(prototype, descriptors) :创建一个具有指定原型且可选择性地包含指定属性的对象

参数:
prototype 必需。  要用作原型的对象。 可以为 null。
descriptors 可选。 包含一个或多个属性描述符的 javascript 对象。
“数据属性”是可获取且可设置值的属性。 数据属性描述符包含 value 特性,以及 writable、enumerable 和 configurable 特性。

如果未指定最后三个特性,则它们默认为 false。 只要检索或设置该值,“访问器属性”就会调用用户提供的函数。 访问器属性描述符包含 set 特性和/或 get 特性。

复制代码
var pt = {
        say : function(){
            console.log(\'saying!\');    
        }
    }
    
    var o = Object.create(pt);
    
    console.log(\'say\' in o); // true
    console.log(o.hasOwnProperty(\'say\')); // false
复制代码

如果prototype传入的是null,创建一个没有原型链的空对象。

var o1 = Object.create(null);
console.dir(o1); // object[ No Properties ]

 当然,可以创建没有原型链的但带descriptors的对象;

复制代码
var o2 = Object.create(null, {
        size: {
            value: "large",
            enumerable: true
        },
        shape: {
            value: "round",
            enumerable: true
        }    
    });
    
    console.log(o2.size);    // large
    console.log(o2.shape);     // round
    console.log(Object.getPrototypeOf(o2));     // null
复制代码

也可以创建带属性带原型链的对象:

复制代码
var pt = {
        say :
function(){
            console.log(
\'saying!\');   
        }
    }

var
o3 = Object.create(pt, { size: { value: "large", enumerable: true }, shape: { value: "round", enumerable: true } }); console.log(o3.size); // large console.log(o3.shape); // round console.log(Object.getPrototypeOf(o3)); // {say:...}
复制代码

 最重要的是实现继承,看下面实例:

复制代码
//Shape - superclass
        function Shape() {
          this.x = 0;
          this.y = 0;
        }
        
        Shape.prototype.move = function(x, y) {
            this.x += x;
            this.y += y;
            console.info("Shape moved.");
        };
        
        // Rectangle - subclass
        function Rectangle() {
          Shape.call(this); //call super constructor.
        }
        
        Rectangle.prototype = Object.create(Shape.prototype);
        
        var rect = new Rectangle();

        console.log(rect instanceof Rectangle); //true.
        console.log(rect instanceof Shape); //true.
        
        rect.move(); //"Shape moved."
复制代码

 不支持浏览器的兼容实现:

1、简单实现,也是最常见的实现方式,没有实现第二个参数的功能:

复制代码
if (!Object.create) {
    Object.create = function (o) {
        if (arguments.length > 1) {
            throw new Error(\'Object.create implementation only accepts the first parameter.\');
        }
        function F() {}
        F.prototype = o;
        return new F();
    };
}
复制代码

2、复杂实现,实现第二个参数的大部分功能:

复制代码
if (!Object.create) {

    // Contributed by Brandon Benvie, October, 2012
    var createEmpty;
    var supportsProto = Object.prototype.__proto__ === null;
    if (supportsProto || typeof document == \'undefined\') {
        createEmpty = function () {
            return { "__proto__": null };
        };
    } else {
        createEmpty = function () {
            var iframe = document.createElement(\'iframe\');
            var parent = document.body || document.documentElement;
            iframe.style.display = \'none\';
            parent.appendChild(iframe);
            iframe.src = \'javascript:\';
            var empty = iframe.contentWindow.Object.prototype;
            parent.removeChild(iframe);
            iframe = null;
            delete empty.constructor;
            delete empty.hasOwnProperty;
            delete empty.propertyIsEnumerable;
            delete empty.isPrototypeOf;
            delete empty.toLocaleString;
            delete empty.toString;
            delete empty.valueOf;
            empty.__proto__ = null;

            function Empty() {}
            Empty.prototype = empty;
            // short-circuit future calls
            createEmpty = function () {
                return new Empty();
            };
            return new Empty();
        };
    }

    Object.create = function create(prototype, properties) {

        var object;
        function Type() {}  // An empty constructor.

        if (prototype === null) {
            object = createEmpty();
        } else {
            if (typeof prototype !== "object" && typeof prototype !== "function") {

                throw new TypeError("Object prototype may only be an Object or null"); // same msg as Chrome
            }
            Type.prototype = prototype;
            object = new Type();

            object.__proto__ = prototype;
        }

        if (properties !== void 0) {
            Object.defineProperties(object, properties);
        }

        return object;
    };
}

前端开发者进阶之ECMAScript新特性【一】--Object.create

 

Object.create(prototype, descriptors) :创建一个具有指定原型且可选择性地包含指定属性的对象

参数:
prototype 必需。  要用作原型的对象。 可以为 null。
descriptors 可选。 包含一个或多个属性描述符的 JavaScript 对象。
“数据属性”是可获取且可设置值的属性。 数据属性描述符包含 value 特性,以及 writable、enumerable 和 configurable 特性。

如果未指定最后三个特性,则它们默认为 false。 只要检索或设置该值,“访问器属性”就会调用用户提供的函数。 访问器属性描述符包含 set 特性和/或 get 特性。

复制代码
var pt = {
        say : function(){
            console.log(\'saying!\');    
        }
    }
    
    var o = Object.create(pt);
    
    console.log(\'say\' in o); // true
    console.log(o.hasOwnProperty(\'say\')); // false
复制代码

如果prototype传入的是null,创建一个没有原型链的空对象。

var o1 = Object.create(null);
console.dir(o1); // object[ No Properties ]

 当然,可以创建没有原型链的但带descriptors的对象;

复制代码
var o2 = Object.create(null, {
        size: {
            value: "large",
            enumerable: true
        },
        shape: {
            value: "round",
            enumerable: true
        }    
    });
    
    console.log(o2.size);    // large
    console.log(o2.shape);     // round
    console.log(Object.getPrototypeOf(o2));     // null
复制代码

也可以创建带属性带原型链的对象:

复制代码
var pt = {
        say :
function(){
            console.log(
\'saying!\');   
        }
    }

var
o3 = Object.create(pt, { size: { value: "large", enumerable: true }, shape: { value: "round", enumerable: true } }); console.log(o3.size); // large console.log(o3.shape); // round console.log(Object.getPrototypeOf(o3)); // {say:...}
复制代码

 最重要的是实现继承,看下面实例:

复制代码
//Shape - superclass
        function Shape() {
          this.x = 0;
          this.y = 0;
        }
        
        Shape.prototype.move = function(x, y) {
            this.x += x;
            this.y += y;
            console.info("Shape moved.");
        };
        
        // Rectangle - subclass
        function Rectangle() {
          Shape.call(this); //call super constructor.
        }
        
        Rectangle.prototype = Object.create(Shape.prototype);
        
        var rect = new Rectangle();

        console.log(rect instanceof Rectangle); //true.
        console.log(rect instanceof Shape); //true.
        
        rect.move(); //"Shape moved."
复制代码

 不支持浏览器的兼容实现:

1、简单实现,也是最常见的实现方式,没有实现第二个参数的功能:

复制代码
if (!Object.create) {
    Object.create = function (o) {
        if (arguments.length > 1) {
            throw new Error(\'Object.create implementation only accepts the first parameter.\');
        }
        function F() {}
        F.prototype = o;
        return new F();
    };
}
复制代码

2、复杂实现,实现第二个参数的大部分功能:

复制代码
if (!Object.create) {

    // Contributed by Brandon Benvie, October, 2012
    var createEmpty;
    var supportsProto = Object.prototype.__proto__ === null;
    if (supportsProto || typeof document == \'undefined\') {
        createEmpty = function () {
            return { "__proto__": null };
        };
    } else {
        createEmpty = function () {
            var iframe = document.createElement(\'iframe\');
            var parent = document.body || document.documentElement;
            iframe.style.display = \'none\';
            parent.appendChild(iframe);
            iframe.src = \'javascript:\';
            var empty = iframe.contentWindow.Object.prototype;
            parent.removeChild(iframe);
            iframe = null;
            delete empty.constructor;
            delete empty.hasOwnProperty;
            delete empty.propertyIsEnumerable;
            delete empty.isPrototypeOf;
            delete empty.toLocaleString;
            delete empty.toString;
            delete empty.valueOf;
            empty.__proto__ = null;

            function Empty() {}
            Empty.prototype = empty;
            // short-circuit future calls
            createEmpty = function () {
                return new Empty();
            };
            return new Empty();
        };
    }

    Object.create = function create(prototype, properties) {

        var object;
        function Type() {}  // An empty constructor.

        if (prototype === null) {
            object = createEmpty();
        } else {
            if (typeof prototype !== "object" && typeof prototype !== "function") {

                throw new TypeError("Object prototype may only be an Object or null"); // same msg as Chrome
            }
            Type.prototype = prototype;
            object = new Type();

            object.__proto__ = prototype;
        }

        if (properties !== void 0) {
            Object.defineProperties(object, properties);
        }

        return object;
    };
}

以上是关于前端开发者进阶之ECMAScript新特性--Object.create的主要内容,如果未能解决你的问题,请参考以下文章

进阶学习10:ECMAScript——ES2016ES2017新特性

从入门到进阶,全面剖析 Angular 2 新特性 | 高手问答精粹

ECMAScript 2016, 2017, 2018 新特性之必读篇

ECMAScript 6新特性之Proxy

ECMAScript6新特性之Reflect

ECMAScript5新特性之isSealedseal