Js对象

来自《你不知道的JavaScript》第3章对象的学习总结

<============================================================>

对象定义有两种方法:声明(文字)形式和构造形式

对象文字形式:

    var myObj = {

        key:value

    }

构造形式:

 var myObj = new Object();

  myObj.key = value;

<============================================================>

简单基本类型:string、number、boolean、null、undefined、object

内置对象:String、Number、Boolean、Object、Function、Array、Date、RegExp、Error

(不同的对象在底层都表示为二进制,在JS中前三位都为0的话会被判断为object类型,null的二进制表示全是0,自然前三位都是0,所以执行typeof时会返回“object”)

<============================================================>

属性与方法:

var myObject = {

    foo:function(){

        console.log("foo");

    };

    var someFoo = myObject.foo;

    someFoo; //function foo(){..}

    myObject.foo;//function foo(){}

}

即使在对象一文字形式声明一个函数表达式,这个函数也不会“属于”这个对象。

<=============================================================>

数组:

var myArray = ["foo",42,"bar"];

myArray["3"] = "baz";

myArray.length;//4

myArray[3] ;//"baz"

如果试图向数组添加一个属性,但是属性名看起来像一个“数字”,那它会变成一个数值下标(所以会修改数组的内容而不是添加一个属性)

 

var myArray = ["foo",42,"bar"];

myArray.baz = "baz";

myArray.length;//3

myArray.baz;//"baz"

 <=============================================================>

属性描述符:

 

  1. writable:决定是否可以修改属性的值
  2. configurable:只要属性是可配置的,就可以使用defineProperty(..)方法来修改属性描述符(即便属性是configurable:false,我们还是可以把writable的状态由true改为false,但无法由false改为true,别外,configurable:false会禁止删除这个属性)

<==============================================================>

遍历:

for..in循环可以用来遍历对象的可枚举属性列表(包括[[Prototype]]链)。

ES5增加了一组数组的辅助迭代器,包括forEach(..)、every(..)和some(..)。

forEach(..)会遍历数组中的所有值并忽略回调函数的返回值;every(..)会一直运行直到回调函数返回false(或者“假”值),some(..)会一直运行直到回调函数返回true(或者“真”值)。

<==============================================================>

存在性

in操作符会检查属性是否在对象及其[[Prototype]]原型链中,可枚举。而hasOwnProperty(..)只会检查属性是否在myObject对象中,不会检查[[Prototype]]链。

var myObject = {

    a:2

}

("a" in myObject);//true

("b" in myObject);//false

myObject.hasOwnProperty("a");//true

myObject.hasOwnProperty("b");//false

看起来in操作符可以检查容器内是否有某个值,但是他实际上检查的是某个属性名是否存在。对于数组来说这个区别非常重要,4 in [2,4,6]的结果并不是true,因为[2,4,6]这个数组中包含的属性名是0、1、2,没有4。

propertyIsEnumerable(..)会检查给定的属性名是否直接存在于对象中(而不是在原型链上)并且满足enumberable:true

Object.keys(..)会返回一个数组,包含所有可枚举属性,不包括原型链上的属性。Object.getOwnPropertyNames(..)会返回一个数组,包含所有属性,无论他们是否可枚举,Object.keys(..)和Object.getOwnPropertyNames(..)都只会查找对象直接包含的属性,不包括原型链上面的。

ES6增加了一种用来遍历值而不是数组下标(或者对象属性)的for..of循环语法。

var myArray = [1,2,3];

for(var v of myArray){

    console.log(v);

}

//1

//2

//3

 

//部分DEMO

   var myArray = ['Hello', 'World!'];

        myArray.bar = "nice to meet you!";

        console.log(myArray.length); //2

        myArray['baz'] = "Good luck to you!";

        console.log(myArray.length); //2

 

        for (var idx in myArray) {

            console.log(idx, myArray[idx]);

            //0 Hello

            //1 World!

            //bar nice to meet you!

            //baz Good luck to you!

        }

 

        var myObj = {};

        Object.defineProperty(myObj, "a", {

            //value:2

            //property descriptors must not specify a value or be writable when a getter or setter has been specified

            //  writable:true,

            configurable: true,

            enumerable: true,

            get: function () {

                return this._a_ * 3;

            },

            set: function (val) {

                this._a_ = val * 2;

            }

        });

        myObj.a = 2;

        console.log(myObj.a); //12

        Object.defineProperty(myObj, "b", {

            writable: false, //决定是否可以修改属性的值(是否可写)

            configurable: true, //只要属性是可配置的,就可以使用defineProperty(..)方法来修改属性描述符

            enumerable: true,

            value: 2

        });

        myObj.b = 3;

        console.log(myObj.b); //2

        Object.defineProperty(myObj, "b", {

            get: function () {

                return 5;

            },

 

            set: function () {

                //  throw new Error('this value is not writable!');

            }

        });

        myObj.b = 3; // [显示/隐藏消息细节。] Error: this value is not writable!

        console.log(myObj.b); //5

 

        Object.defineProperty(myObj, "c", {

            writable: true, //决定是否可以修改属性的值(是否可写)

            configurable: false, //只要属性是可配置的,就可以使用defineProperty(..)方法来修改属性描述符

            enumerable: true,

            value: 4

        });

 

        console.log(myObj.c); //4

        myObj.c = 5;

        console.log(myObj.c); //5

 

        delete myObj.c;

        console.log('hi', myObj.c); //hi 5


 

        //即便属性是configurable,依旧可以将writable的状态由true改为false

        Object.defineProperty(myObj, "c", {

            writable: false, //决定是否可以修改属性的值(是否可写)

            //用户定义的所有的普通属性默认都是enumerable:true,这通常就是我们想要的。但是如果你不希望某些特殊属性

            //出现在枚举中,可以将其设置为enumerable:false

            configurable: false, //只要属性是可配置的,就可以使用defineProperty(..)方法来修改属性描述符

            enumerable: true,//false can't redefine non-configurable property "c"

            value: 4

        });

 

        console.log('------------------------------');

 

        //不管是不是处于严格模式,尝试修改一个不可配置的属性描述符都会出错!

        //所以configurable修改成false是单向操作,无法撤销,别:configurable:false会禁止删除该属性

        Object.defineProperty(myObj, "c", {

            writable: true, //决定是否可以修改属性的值(是否可写)

            configurable: true, //只要属性是可配置的,就可以使用defineProperty(..)方法来修改属性描述符

            enumerable: true,//控制的是属性是否会出现在对象的属性枚举中,比如说for..in循环。

            value: 6

        }); //TypeError:can't redefine non-configurable property "c"

 

        //禁止一个对象添加新属性并且保留已有属性,可以使用Object.preventExtensions(..)

        var myObject = {

            a:2

        };

        Object.preventExtensions(myObject);

        myObject.b=2;

        console.log(myObject.b);//undefined

 

        //密封Object.seal(..)会创建一个冻结对象,这个方法实际上会在一个现有对象上调用Object.preventExtensions(..)

        //并把所有现有属性标记为configurable:false

        var myObject1 = {

            a:1,

            b:2,

            c:3

        }

        Object.seal(myObject1);

        myObject1.d=4;

        console.log(myObject1.d);//undeined

 

        //冻结Object.freeze(..)会创建一个冻结对象,这个方法实际上会在一个现有对象上调用Object.seal(..)并把所有

        //"数据访问"属性标记为writable:false,这样就无法修改它们的值。(不过这个对象引用的其他对象是不受影响的!)

 

//对象默认的[[PUT]]和[[GET]]操作分别可以控制属性值的设置和获取

        //[[PUT]]被触发时,实际行为取决与诸多因素。包括对象中是否已经存在该属性(这是最重要的因素)

        //如果已经存在该属性,[[PUT]]算法大致会检查下面这些内容。

        //1.属性是否是访问描述符(GETTER、SETTER或两者都有)?如果是并且存在SETTER就调用SETTER

        //2.属性的数据描述符中writable是否是false?如果是,在非use strict(严格模式)下静默失败,

        //在严格模式下抛出TypeError异常。

        //3.如果都不是,将改值修改为属性的值。

 

        //对应访问描述符来说,javascript会忽略他们的value和writable特性,

        //取而代之的是关心set和get(还有configurable和enumerable)特性。

        //getter是一个隐藏函数,会在获取属性值时调用。setter也是一个隐藏函数,会在设置属性值是调用。


 

        //无论是对象文字语法中的get a(){..},还是defineProperty的显式定义,两者都会在对象中创建一个不包含值的属性,对

        //于这个属性的访问会自动调用一个隐藏函数,他的返回值会被当做属性访问的返回值。

        //文字语法get a(){..}

        var obj = {

            //给a定义一个getter

            get a() {

                return 2;

            }

        };

 

        //defineProperty显式定义

        Object.defineProperty(

            obj, //目标对象

            "b", //属性名

            //描述符

            {

                //给b设置一个getter

                get: function () {

                    return this.a * 2

                },

                enumerable: true //确保b会出现在对象的属性列表中

            });

 

        obj.a; //2

        obj.b; //4

 

    //一般gettter和setter成对出现,setter会覆盖单个属性默认的[[PUT]](也成为赋值操作)操作

   //访问属性时,引擎实际上会调用内部默认的[[GET]]操作,如果无法在对象本事找到需要的属性,会继续访问对象的[[Prototype]]链。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值