Js学习笔记 - 初识Js对象

作者: Ursus_M | 来源:发表于2016-11-14 15:58 被阅读50次

    前言

    最近在廖雪峰的官方网站,看了一些Javascript的相关教程,感觉这套教程里的思路还是挺清晰明了的,该篇读书笔记就是将其中对象方面的内容进行了一个总结性的整理。

    关于js中的对象

    格式

    var hero = {
        name: 'hero',
        sex: 'male' ,
        'code-name': 'codename',
        shoot: function () {
            console.log(this.name + ' is shooting');
        }
        info: function () {
            console.log('name:' + this.name + '\n'
                + 'sex:' + this['sex'] + '\n'
                + 'code-name:' + this['code-name']);
        }
    };
    

    在javascript中,对象是以键值对的形式存在的,格式上:

    1. 格式和json有点类似,用 {} 括起来,属性和值之间用 : 隔开,而非 =
    2. 每组键值对(属性与值)之间用 , 隔开
    3. 如果属性名中包含特殊字符,比如 - 的话,属性名要用 ''括起来
    4. 属性的值可以是一个函数

    用法

    调用
    console.log('name:' + hero.name + '\n'
                + 'sex:' + hero['sex'] + '\n'
                + 'code-name:' + hero['code-name']);
                
    hero.shoot();
    hero.info();
    
    1. 直接用 变量.属性 或者 变量['属性'],如果属性名是用 '' 隔开的只能用 变量['属性'] 方式
    2. 如果属性是方法,也是用 变量.属性(参数..)的方式调用。
    属性增加删除
        console.log(hero.height);//undefined
        
        hero.height = 180;//添加属性
        console.log(hero.height);//180
        
        delete hero.height;//删除属性
        console.log(hero.height);//undefined
    
    

    添加的话,直接赋值即可。删除时,如果属性不存在也不会报错

    判断属性是否存在

    判断属性存在有两种方式

    1. '属性名' in '变量', 返回true/false,存在true,不存在就是false。如果该属性是继承下来的属性那么同样返回 true
    2. hasOwnProperty方法,返回 true/false,存在true,不存在就是false。只有是自身属性才返回true。
       console.log('name' in hero);//true
       console.log('height' in hero);//false
       console.log('toString' in hero);//true
    
       hero.hasOwnProperty('name');//true
       hero.hasOwnProperty('height');//false
       hero.hasOwnProperty('toString');//false
    

    特性

    _proto_ 和 Object.create()

    将A对象的原型指向B对象,那么A对象就获得了B对象中的属性

        var dva = {
            name: 'D.VA',
            height: 180,
        }
        dva.__proto__ = hero;
        dva['code-name'];//codename
    

    不过一般不直接使用对象的 __protp__ 属性,部分浏览器不支持,通常的做法是使用 Object.create 方法

        function createStudent(name) {
            var s = Object.create(hero);
            s.name = name;
            return s;
        }
        var mercy = createStudent("mercy");
        mercy['code-name'];//codename
    
    new一个对象

    js中 用 new 调用一个函数会返回一个新创建的对象,该函数中的 this 就指向这个新创建的对象。

        function Map(name) {
            this.name = name;
            this.start = function () {
                console.log('正在前往' + name);
            }
        }
    
        var Dorado = new Map('多拉多');
        Dorado.name;//多拉多
        Dorado.start();//正在前往多拉多
    
        var Numbani = new Map('努巴尼');
        Numbani.name;//努巴尼
        Numbani.start();//正在前往努巴尼
    

    js中调用普通函数,会返回一个 undefined

    原型链
    js原型链

    当在js中访问某个对象的属性时(obj.xxx

    1. 首先会在改对象中查找该属性
    2. 如果第1步找不到该属性,就会从该对象的原型对象中查找(该对象 __proto__ 属性指向的对象)
    3. 找不到的话会一直找下去,直到找到 Object.prototype,如果还没有就会返回undefined。

    这样就形成了原型链

    Dorado ----> Map.prototype ----> Object.prototype ----> null

        Dorado.__proto__ === Map.prototype;//true
        Map.prototype.__proto__ === Object.prototype;//true
        Object.prototype.__proto__ === null;//true
        Dorado.constructor === Map;//true
    

    上面对象中 _Dorado__Numbani_ 中的 _start_ 属性一个函数,函数名和代码都相同,根据原型链,DoradoNumbani 上找不到的属性,会从他们的原型上找,于是我们可以将 _start_ 属性移动到 Map.prototype上。

        function Map(name) {
            this.name = name;
        }
    
        Map.prototype.start = function () {
            console.log('正在前往' + this.name);
        };
    
    jsc_pic002.png
    create一个对象三步曲
    1. 创建构造函数
    2. 添加通用方法
    3. 封装构造函数
        //第一步:创建构造函数(首字母一般大写,用于和普通函数区分)
        function Map(props){
            this.name = props.name || '训练靶场';
        }
    
        //第二步:添加通用方法(方法写在构造函数prototype中)
        Map.prototype.start = function () {
            console.log('正在前往' + this.name);
        }
    
        //第三步:封装构造函数(把构造函数封装一下,省的调用的时候每次都写new)
        function createMap(props){
            return new Map(props || {});
        }
    
        var Trainrang = createMap();
        Trainrang.start();//正在前往训练靶场
    
        var Nepal = createMap({
            name : '尼泊尔'
        });
        Nepal.start();//正在前往尼泊尔
    
    原型继承

    当一个对象中的某个属性找不到时,会在原型上去找,所以可以通过原型在js中完成继承操作。
    如果想创建Map的一个子类FestvialMap,那么FestvialMap的原型链应该是:
    FerguGym ----> FestivalMap.prototype ----> Map.prototype ----> Object.prototype ----> null

    js原型链

    如上图,最简单的方式就是将 FestivalMap.prototype.__proto__ = Map.prototype,不过一般不会直接操作对象的__proto__属性。于是采用下面的方案

    1. 创建一个空函数 M ,这时 new M() 对象的 __proto__ 属性就指向了 M.prototype
    2. M.prototype 赋值为 Map.prototype,这时 new M() 对象的 __proto__就指向了 Map.prototype
    3. FestivalMap.prototype 赋值为 new M(),这时 FestivalMap.prototype 对象的 __proto__就指向了 Map.prototype
    4. 由于现在的 FestivalMap.prototype 就是刚才新创建的 new M(),将他的 constructor 属性指向他本身
        function FestivalMap(props) {
            Map.call(this, props);
        }
    
        function createFestivalMap(props) {
            return new FestivalMap(props || {});
        }
    
        //创建一个空函数 M ,这时 new M() 对象的 __proto__ 属性就指向了 `M.prototype`
        function M() {
    
        }
    
        //将 M.prototype 赋值为 Map.prototype,这时 new M() 对象的 __proto__就指向了 Map.prototype
        M.prototype = Map.prototype;
        
        //将 FestivalMap.prototype 赋值为 new M(),这时 FestivalMap.prototype 对象的 __proto__就指向了 Map.prototype
        FestivalMap.prototype = new M();
        
        //由于现在的 FestivalMap.prototype 就是刚才新创建的 new M(),将他的 constructor 属性指向他本身
        FestivalMap.prototype.constructor = FestivalMap;
        
        FestivalMap.prototype.type = function () {
            console.log('特殊地图:' + this.name)
        }
        
        var FerguGym = createFestivalMap({
            name: '弗格体育场',
    
        });
        console.log(FerguGym.name);//弗格体育场
        FerguGym.start();//正在前往弗格体育场
        FerguGym.type();//特殊地图:弗格体育场
    

    封装这几步

        function inherits(Child,Parent){
            var F = function(){};
            F.prototype = Parent.prototype;
            Child.prototype = new F();
            Child.prototype.constructor = Child;
        }
    
    class继承

    在ES6新增了用关键字 class 来定义类的方式,和原型类继承原理是一样的,只是简化了代码。

        class Map {
        
            //构造方法
            constructor(name) {
                this.name = name || '训练靶场';
            }
    
            //相当于之前的 Map.prototype.start = function(){...},前面不加function
            start() {
                console.log('正在前往' + this.name);
            }
        }
    
        var LijiangTower = new Map('漓江塔');
        LijiangTower.start();//正在前往漓江塔
    
        class FestivalMap extends Map {
            constructor(name) {
                //调用父类构造方法
                super(name);
            }
    
            type() {
                console.log('特殊地图:' + this.name);
            }
        }
    
        var FerguGym = new FestivalMap('弗格体育场');
        FerguGym.start();//正在前往弗格体育场
        FerguGym.type();//特殊地图:弗格体育场
    

    相关文章

      网友评论

      本文标题:Js学习笔记 - 初识Js对象

      本文链接:https://www.haomeiwen.com/subject/trbhpttx.html