说说对象那些事儿,(属性行为,原型链)

声明 本文仅用于学习交流,切勿用作其他用途。

[TOC]


js 本来是没有对象的,不知道是不是因为单身久了,所以被迫有了对象。


对象创建

对象创建一般我们都是通过new function来的,Es6中可以直接写class,这样子用法就是new一个class了。
当然也可以使用Object.create 和 Object.assign

对象的属性行为,这可是很有意义的


说到这个属性行为呀,我想起了基础数据类型的Symbol,以这个Symbol作为key值的对象,通过for...in 是拿不到这个Symbol的,不信大可以试试如下代码

    var smb = Symbol("key1");
    var a = {};
    a[smb] = "hello wolrd";

    console.log(Object.keys(a)) ;//看看这里是不是打印的[]就知道啦

    //之前说过哦,要通过Object.getOwnPropertySymbols才能拿到哦
    console.log(Object.getOwnPropertySymbols(a)) ;//[Symbol(key1)]

对于对象的属性行为,目前有 configurable,writable,enumerable,value

这个属性行为,其实说白了,和c++成员私有公有差不多的感觉,对于大家使用 Object.defineProperty的情况我不是很清楚,但是至少在我看到 '怎么在Es5中定义常量' 之前我是没怎么使用的,都是用已有的一些类呀什么直接拿过来用,或者直接把类当做hashMap来用...


定义常量

    //浏览器下面可以用下述方法设置常量。
    function setConst(name,value,log){
        (log === undefined) && (log = true);
        if(typeof name == 'string' && !name){
            if( !window.hasOwnProperty(name)){
                Object.defineProperty(window,name,{
                    configurable:false,//避免用defineProperty修改
                    writable:false,//不可写入
                    value:value
                })
            }else{
                log && console.warn("const variable name",name,"already exists")
            }
        }else{
            log && console.warn("name",name," is illegal")
        }
    }

    //useage
    setConst("Five",5);
    console.log(Five);//5
    setConst("Five",6);
    console.log(Five);//5
    Five = 7;
    console.log(Five);//5

如上所示,js可以设置类的可写属性,枚举属性,是否可以修改对象属性的属性,以及值。

configurable

为false的时候,delete,defineProperty操作无效

writable

为false的时候 字面意思,不可更改,重新赋值无效

enumerable

为 false时,不出现在枚举列表,即Object.keys() 不能拿到对应的key

value

默认 undefined ,如字面意思,值


对象创建方式

  • new function
  • Object的操作,如Object.assign ,Object.create
  • 直接以JSON的形式创建 --如 var a = { h:xxx }
  • new class --等价于new function

new function

    function T(){

    }


    var t = new T();//new function的时候返回的是一个类

    var r = T();//这种情况就是执行一个function,没有new就是普通执行


    //----------------------------------------------------
    function F(){
        (typeof this != 'undefined') && (this.t = "hello");
        //如果这里没有返回或者返回不是对象,那么使用new的时候就返回this对象,
        //如果这里返回了对象,那就不会返回this了

        ///////////////////////////////////////////////////
        var t = {t:"test"};
        return t;//这样写就是在玩火。不管怎么new,都是返回{t:"test"}这个对象,虽然引用不一样
        ///////////////////////////////////////////////////
    }
    var t = new F();//或者F() 
    console.log(t.t);//‘test’



    //----------------------------------------------------
    function G(){
        if(new.target){ //我们可以这样检验调用的时候是否使用了new
            //....
        }
    }


Object的操作

Object.creat方法创建一个新对象,使用现有的对象来提供新创建的对象的proto。 ;

Object.assign 方法用于将所有可枚举属性的值从一个或多个源对象复制到目标对象。它将返回目标对象。

    //////////////////
    var b = {k:1,k2:2};
    var a  = Object.create(b);//这里会创建对象a,把b作为a的原型,
    console.log(a.k,a.k2,a.__proto__ == b)
    b.k = 3,b.k2 = 4;
    console.log(a.k,a.k2);// 3,4

    var c  = Object.create(a,{
        key1:{
            value: "this is a test case", 
            writable: true,
            enumerable: false,
            configurable: true 
        },
        key2:{
            value: "this is read-only value", 
            writable: false,
            enumerable: true,
            configurable: true 
        }
    });//这里会把a作为c的原型,并且增加val属性,该属性的行为可以自行定义
    
    console.log(c,c.key1 ) ;
    console.log(c.k,c.k2);//3,4 这个就涉及到了原型链了

    

    /////////////////////
    var d = Object.assign(c,{k:6,k2:5},undefined,5,null,"hello",{});
    console.log(d) ;// {k:6,k2:5,'0': 'h', '1': 'e', '2': 'l', '3': 'l', '4': 'o'}
    //MDN上面说 原始类型会被包装,null 和 undefined 会被忽略。只有字符串的包装对象才可能有自身可枚举属性

    //拷贝的是引用地址值来着。原型链中的和不可枚举的都不能拷贝。返回值是目标对象,也就是如下
    console.log(c == d);//true


直接以JSON的形式创建

    //////////////////
    var a = {
        key1:"1",
        key2:2,
        key3:false,
        func4:function(){
            return this.key1;
        }
    }

    console.log(a.func4())

    var b = JSON.parse('{ "t":1,"k":"hello","m":"world"} ')
    console.log(b);//{ t: 1, k: 'hello', m: 'world' }

new class

    //////////////////
    class cls{

        set key1(val){
            this._key1 = val;
        }
        get key1(){
            return this._key1;
        }

        constructor(){
            this._key1 = "test";
        }
    }
    var a = new cls();

    //相当于 
    //function cls(){ this._key1 = "test" };
    //var a = new cls();
    //Object.defineProperty(a,"key1",{
    //set:function(v){ this._key1 = v},get:function(){ return this._key1}
    //})

原型链与继承

参照 https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Inheritance_and_the_prototype_chain

原型链

关于这个原型链我的理解有些不到位,欢迎大家指出我的错误的理解,

我的理解大概就是原型链就是对象的一个查找表,类似lua的原表,当我们试图 obj['key1'] 时,会先在obj下查找key1是否存在,没找到的情况再去 obj.__proto__ 去查找,如果还没找到则去 obj.__proto__.__proto__ 去查找,依次类推,直到找到或者遍历完原型链。

这个查找的概念就是在使用 obj['key'] 或者 obj.key 时执行的查找。

    var a = { b :1,c:"2"  }
    var b = Object.create(a);//创建对象,指定对象的原型是a,
    console.log(b);//{}
    console.log(b.b,b.c);//这里在b里面没找到b和c属性,所以去原型链找
    console.log(b.__proto__ == a);//true

所以我对原型链的理解为:对象所具有的默认值,修改原型链中的这个值(__proto__.xxx)会影响具有相同原型链的其他对象,但是在自身增加对象则会覆盖这个值,如下

  function T(){

  }
  T.prototype.test = 1;

  var t1 = new T(),t2 = new T();;
  console.log(t1.test,t2.test);//1,1
  t1.__proto__.test = 2;
  console.log(t1.test,t2.test);//2,2
  t2.test = "hello";
  console.log(t1.test,t2.test);//2,hello

继承

这个是个大问题,毕竟js不是面向对象的,所以感觉原型链很大一部分感觉是为了继承而生的。

其操作大概就是 childCls.prototype = parent

我们用Object.create来创建对象的时候,实际上就是一个继承了。只是有时候可能没有那么明确,上面的原型链中的数据,也就是说继承之后的初始值,我们可以在继承之后去更改这些值。这个继承给人的感觉,很隐蔽。


最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,099评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,828评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,540评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,848评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,971评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,132评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,193评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,934评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,376评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,687评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,846评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,537评论 4 335
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,175评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,887评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,134评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,674评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,741评论 2 351

推荐阅读更多精彩内容

  • 什么是原型语言 只有对象,没有类;对象继承对象,而不是类继承类。 “原型对象”是核心概念。原型对象是新对象的模板,...
    zhoulujun阅读 2,324评论 0 12
  • JS中原型链,说简单也简单。 首先明确: 函数(Function)才有prototype属性,对象(除Object...
    前小白阅读 3,917评论 0 9
  •   面向对象(Object-Oriented,OO)的语言有一个标志,那就是它们都有类的概念,而通过类可以创建任意...
    霜天晓阅读 2,098评论 0 6
  • 儿时 对山那边的世界感到好奇如今明白 山那边一直住在心里攀上一座座山就是迈过心里的一道道坎一次次站在山顶对灵魂一次...
    翊寒阅读 839评论 8 19
  • 时间过得很快,一年光景就这样过去了,又一年新生在9月10号这一天如约而至。过去的一年作为小师妹在师兄师姐的关照下成...
    晓娟啊阅读 184评论 0 0