• 原型笔记


    • 1. Object.getOwnPropertyNames()

      在学习使用该方法的时候,查阅了《JavaScript高级程序设计》与 MDN 来综合学习。

      先来看看MDN对其的表述:

      参数

         obj:
      一个对象,其自身的可枚举和不可枚举属性的名称被返回。

      返回值

          在给定对象上找到的属性对应的字符串数组。

       描述

        Object.getOwnPropertyNames() 返回一个数组,该数组对元素是 obj自身拥有的枚举或不可枚举属性名称字符串。 数组中枚举属性的顺序与通过 for...in 循环(或 Object.keys)迭代该对象属性时一致。数组中不可枚举属性的顺序未定义。

      

      同时,举出了几个例子来表显示,例如:

    var arr = ["a", "b", "c"];
    console.log(Object.getOwnPropertyNames(arr).sort()); // ["0", "1", "2", "length"]
    
    // 类数组对象
    var obj = { 0: "a", 1: "b", 2: "c"};
    console.log(Object.getOwnPropertyNames(obj).sort()); // ["0", "1", "2"]
    
    // 使用Array.forEach输出属性名和属性值
    Object.getOwnPropertyNames(obj).forEach(function(val, idx, array) {
      console.log(val + " -> " + obj[val]);
    });
    // 输出
    // 0 -> a
    // 1 -> b
    // 2 -> c
    
    //不可枚举属性
    var my_obj = Object.create({}, {
      getFoo: {
        value: function() { return this.foo; },
        enumerable: false
      }
    });
    my_obj.foo = 1;
    
    console.log(Object.getOwnPropertyNames(my_obj).sort()); // ["foo", "getFoo"]

      正如:MDN上所述,该方法返回的是对象自身的可枚举与不可枚举属性,即返回的是一个数组。并且在查阅《JavaScript高级程序设计》这本书籍的时候,却发现了一个问题。

    function Person(){
    
    }
    
    Person.prototype.name = 'asfd'
    Person.prototype.age = 15
    Person.prototype.sayName = function () {
    console.log(this.name)
    }
    var keys = Object.getOwnPropertyNames(Person.prototype) console.log(keys) 
    // 书籍中表述keys返回的是 ['constructor', 'name', 'age', 'sayName']
    // 但是当将Person.property设置一个以对象字面量形式创建的对象时,就不再返回constructor. 书籍中已经解释此时的constructor不再指向Person
    // 于是,我真的操作了一遍才发现,真的如此
    // 实例如下:
    function Person(){ } Person.prototype = { name: 'zwj', age: 21, say: function () { console.log('say') } }
    var keys = Object.getOwnPropertyNames(Person.property)
    console.log(keys)
    // 此时返回的 ['name','age','sayName']

      我根据书中理解如下:设置一个以对象字面量形式创建的对象,虽然结果相同,但是constructor不再指向Person,这就涉及到原型链了

      首先,每个构造函数被创建的时候,同时就创建了一个构造函数对应的原型对象,即: 构造函数.prototype 

      这个对象就会自动获得一个constructor属性,这个属性就是该对象指向构造函数的指针,你也可以试试输出: Person.prototype    Person.prototype.constructor     Person.prototype.constructor.prototype 等等,就会发现形成了一个闭环...

      这里我们使用的语法去接收属性值,本质上默写了prototype对象,这时候,改写的对象默认的constructor指向为Object构造函数,毕竟函数也是对象,在JS中一切皆为对象...

      所以如果我们通常为了在原型上进行大量的属性写入,就必须对这部分操作进行注意,需要在使用设置对象字面量方式之后手动为其添加constructor属性的指向,这样做的目的就是为了确保通过该属性能够访问到适当的值...

      当然你会觉得这样设置并不是完美,毕竟对于constructor这个属性,他应该是不可枚举的,此时,却是可枚举的,这是就需要我们使用Object.defineProperty()进行相应的设置.相应的代码如下:

    function Person(){
    }
    // 此时重写了prototype对象 constructor指向Object
    Person.prototype = {
      name: 'Nick',
      age: 15,
      sayName: function(){
        consolelog(this.name)
      }  
    }
    // 对constructor进行设置修改
    Object.defineProperty(Person.prototype, 'constructor', {
       enumerable: false,   // 设置是否可枚举  false为不可枚举
       value: Person         // 设置值为Person
    })
    //可以通过definePrototype进行更改数据属性的共有6个,其余4个分别为:
    // configurable  ----------> 表示是否可以通过delete进行删除 默认为true
    // writable        ----------> 表示是否可以修改属性的值 默认为true
    // get ----------> 一个给属性提供 getter 的方法,如果没有 getter 则为 undefined。该方法返回值被用作属性值。默认为 undefined。
    // set --------> 一个给属性提供 setter 的方法,如果没有 setter 则为 undefined。该方法将接受唯一参数,并将该参数的新值分配给该属性。默认为 undefined。

      

      总结: 在进行创建构造函数的时候,以前习惯只是将constructor直接写在重写的prototype对象中,但是却忽略了其中最重要的一条信息,那就是constructor属性本身是不可枚举的属性,还需要更深一层的操作去设置constructor.看问题不能只看表面,更应该注重于内在...

  • 相关阅读:
    Lucene.Net 2.3.1开发介绍 —— 二、分词(一)
    控制‘控制台应用程序’的关闭操作
    详解for循环(各种用法)
    敏捷软件开发
    Sql Server的一些知识点
    在SharePoint 2010 中配置Remote Blob Storage FILESTREAM Provider
    使用LotusScript操作Lotus Notes RTF域
    JOpt Simple 4.5 发布,命令行解析器
    John the Ripper 1.8.0 发布,密码破解工具
    PacketFence ZEN 4.0.1 发布,网络接入控制
  • 原文地址:https://www.cnblogs.com/gxlself/p/9121090.html
Copyright © 2020-2023  润新知