• js对象系列【一】深层理解对象与原型


    我们先从盘古开天辟地时捋一捋对象:

    从宏观内容来讲,javascript是一个属性的集合,包括值,函数,而整个集合也可以类比为一个对象。

    js = {
      a的变量名: a的值,   ...
         函数b: function () {}   ... }

    注: 这里的js指的是javascript对象(ECMAscript对象),而不是DOM和BOM对象。

    紧接着我们听到一个“传说”:‘javascript中一切都是对象’  ,或者说是有这么一个说法,但到底说的正确还是不正确,我们还需要自己追根溯源,挖掘一下:

    从js来讲,变量和方法之间联系很紧密,变量可以通过原生js对象的构造方法创建,而方法又可以通过创建的变量(“对象”)调用,注意这里的对象是带了引号的,这就说明它不是真正意义上的对象,下文会说明原由。

    js中一共由6中基本数据类型:number,string,boolean,null,undefined,symbol(es6新增)

    从属性值方面讲:一个变量可以通过两种方式创建:

    1. 由于js为弱类型语言,所以可直接赋值创建

    var a = 1;
    console.log(typeof a)    // number

    2. 由原生对象通过构造函数创建

    var b = new Number(1);
    console.log(typeof b)  // object

    为确定它们都是数字,我们可以判断一下:

    console.log(a == b)   // true

    由此可知,a和b只是创建方式不同,而a也确实是基本数据类型,但是,基本数据类型又能否向对象一样进行添加属性的操作呢,答案是可以的:

            var a = 1;
            a.prop = 2;   // 不会报错
            console.log(a) // 1
            console.log(a.prop) // undefined
            console.log(a.toString()) // 1 (字符串)

    那么变量a的数据类型为基本数据类型,却又可以进行对象赋值操作(这里只能够赋值,但赋值没有成功),还可以调用对象的方法。

    回想一下,我们经常是通过最简单的方法定义变量(基本类型可以通过直接赋值,引用类型可以通过字面量),而这些方法是为了简化操作。当基本数据类型触发对象行为时,系统会为基本数据类型创建一个包装对象,当对象行为完成后,该包装对象即被销毁。

    现在回来说,js中的一切是不是对象,主要在于对基本数据类型的操作,常规操作时,它只是基本数据类型,特殊使用时,基本类型又会成为包装对象。

    由此,可以总结出,js的一切是不是对象,完全在于你的代码习惯,或者代码功能,确实没有一个确定的答案,主要在于你个人的理解。就像人妖到底是人还是妖,完全在于你在生活中怎么去看待。

    源头说的差不多了,下面我们来具体说明:

    在js中所有通过对象创建的对象,都有一个原型。这些对象都有一个通过原型链接的父级,而这些链接起对象的原型就是原型链。

    在js中,除了null(空对象)和Object.prototype之外,都有原型。通俗来讲,它们没有“爹”。空对象,顾名思义,一切皆空,什么也不是,什么也没有。而Object.prototype是原型链的最顶端,如果你是科班出身,那么你一定听说过链表,这里的Object.prototype也就相当于是链表的根节点。

    做人要 追源溯果,写代码也一样。我们可以通过Object.creat方法创建指定原型的对象

    var a = Object.create(Number.prototype)

    a的父级就是Number,Number的父级是Object。下图可以辅助理解

    此时,a便可以使用Number.prototype对象和Object.prototype中的方法。

    操作属性

    对象的属性还存在属性的特性用以控制对象的属性:值(value),操作性(configurable),可写性(writable),枚举性(numerable)。

            var obj = {
                a: 1,
                b: 2
            }
            Object.defineProperty(obj, 'b', {
                value: 5,
                enumerable:false
            })
            console.log(obj) // {a: 1, b: 5}
            for (var i in obj) {
                console.log(i) // a
            }

    configurable:能否使用delete、能否更改特性,false为不可重新定义

    在此要注意,通过Object.defineProperty()创建的属性,以上三个特性的默认值都是false。

    enumerable值为false的属性会影响三个过程:

    1. 通过for  in遍历对象的过程,无法遍历不可枚举属性

    2.通过Object.keys(obj)返回属性值的过程,无法获得obj中的不可枚举属性名

    3.JSON.stringify(obj)将对象转换为字符串的过程,只返回可枚举属性

    检测属性

    当我们需要检测属性时,可以通过以下三种方式:

            var obj = {
                a: 1,
                b: 2
            }
            Object.defineProperty(obj, 'a', {
                value: 5,
                enumerable:false
            })
            // 方法1 (可判断多有属性,包括继承的属性)
            console.log('a' in obj) // true
            // 方法2 (只可判断自身的属性)
            console.log(obj.hasOwnProperty('a')) // true
            // 方法3 (只可判断自身的可枚举属性)
            console.log(obj.propertyIsEnumerable('a')) // false
            console.log(obj.propertyIsEnumerable('b')) // true

    删除属性

    在删除属性时,delete只会断开属性与宿主对象之间的联系,而不是操作此属性。删除对象的属性时,要深层遍历防止属性值也为对象的情况。

            var obj = {
                a: {
                    x: 1
                },
                b: 0
            }
            var obj2 = obj.a;
            delete obj.a
            console.log(obj)  // {b: 0}
            console.log(obj2.x) // 1

    存取器属性

    类似于外观模式下的get与set方法,get 返回相应的值,set则用于根据场景的不同选择性的设置属性值。

            var stu = {
                name: 'kevin',
                age: 15,
                get change () {
                     return this.name
                },
                set change (name) {
                    if (this.age >= 18) this.name = name
                    else throw '未满18岁不可改名'
                }
            }
            console.log(stu.change)  //  kevin
            stu.change = 'pomelo'
            console.log(stu.name) // 抛出异常

    注:

    1.存取器属性是可以继承的

    2.存取器属性不含有value和writable特性,get代替了value,而set则代替了writable

  • 相关阅读:
    sublime开启vim模式
    git命令行界面
    搬进Github
    【POJ 2886】Who Gets the Most Candies?
    【UVA 1451】Average
    【CodeForces 625A】Guest From the Past
    【ZOJ 3480】Duck Typing
    【POJ 3320】Jessica's Reading Problemc(尺取法)
    【HDU 1445】Ride to School
    【HDU 5578】Friendship of Frog
  • 原文地址:https://www.cnblogs.com/pomelott/p/8082951.html
Copyright © 2020-2023  润新知