JavaScript读书笔记(对象的总结)

JavaScript读书笔记(对象的总结)

1、建立对象的方式

  • 一、直接建立(经常使用)数组

    let obj = {
      name: '哈哈',
      gender: '男'
    }
    复制代码
  • 二、使用实例化对象的方式建立(比较少用)app

    function Foo() {
      //
    }
    let foo = new Foo()
    复制代码
  • 三、内置对象的实例函数

    let x1 = new Object();    // A new Object object
    let x2 = new String();    // A new String object
    let x3 = new Number();    // A new Number object
    let x4 = new Boolean();   // A new Boolean object
    let x5 = new Array();     // A new Array object
    let x6 = new RegExp();    // A new RegExp object
    let x7 = new Function();  // A new Function object
    let x8 = new Date();      // A new Date object
    复制代码
  • 四、使用工厂方式建立(不多用)工具

    function CreatePerson(name, age, sex) {
      var obj = new Object();
      obj.name = name;
      obj.age = age;
      obj.sex = sex;
      obj.sayName = function () {
        return this.name;
      }
      return obj;
    }
    
    let p1 = new CreatePerson('哈哈', 20, '男');
    复制代码

2、一些基本的属性或者方法

  • 一、每个对象都有连接着原型对象的隐藏属性__proto__测试

    var obj = {};
    obj.__proto__ === Object.prototype; //true
    复制代码
  • 二、判断一个对象是否包含一个属性ui

    const obj2 = {gender: '男'};
    
    console.log('gender' in obj2);
    console.log('name' in obj2);
    // 也可使用hasOwnProperty
    console.log(obj2.hasOwnProperty('gender'));
    复制代码
  • 三、判断一个对象是否为空this

    const obj2 = {gender: '男'};
    
    console.log(Object.keys(obj2));
    console.log(Object.values(obj2));
    复制代码
  • 四、删除一个属性spa

    const obj2 = {gender: '男', age: 20, name: '张三'};
    delete obj2.gender;
    console.log(obj2);
    // 也可使用解析赋值的方式
    const {name, ...obj1} = obj2;
    console.log(obj1);
    复制代码
  • 四、Object.assign()的使用prototype

    • 1.对象的合并
    • 2.对象的浅拷贝
    • 3.给对象新增属性/方法
    • 4.克隆对象(非深拷贝)
  • 五、判断是否为对象代理

    Object.prototype.toString.call(data).slice(8, -1)
    复制代码

3、关于对象中几个重要词的理解

  • 一、constructor查找该对象是由什么建立出来的

    let obj = {};
    let reg = new RegExp();
    let arry = new Array();
    let str = new String();
    let date = new Date();
    
    
    console.log(obj.constructor);
    console.log(reg.constructor);
    console.log(arry.constructor);
    console.log(str.constructor);
    console.log(date.constructor);
    // 继续往上面找
    console.log(Date.constructor);
    console.log(Function.constructor);
    复制代码
  • 二、instanceof判断构造函数是否在对象实例的原型链上

    Person.prototype.dance = function () {
      return 'dance function';
    }
    
    // 定义一个子类
    function Foo() {
    }
    
    Foo.prototype = new Person();
    let foo = new Foo();
    
    /** * 修改Foo原型的constructor * 关于defineProperty几个参数的介绍 * 第一个参数:属性所在的对象,第二个参数:属性的名字,一个描素符对象 */
    Object.defineProperty(Foo.prototype, 'constructor', {
      writable: false,
      enumerable: false,
      value: Foo,
    });
    
    let foo1 = new Foo();
    console.log(foo1 instanceof Foo);
    console.log(foo1 instanceof Person);
    console.log(foo1 instanceof Object);
    复制代码
  • 三、hasOwnProperty()判断一个对象是否拥有该属性

    var obj = {name: '哈哈', gender: '男'};
    obj.hasOwnProperty('name');
    复制代码
  • 四、setPrototypeOf()修改对象的原型

    function Foo() {
    };
    const foo = new Foo();
    // 每个对象都有constructor
    let bar = {};
    console.log(bar.constructor);
    // 修改bar的原型
    Object.setPrototypeOf(bar, foo);
    console.log(bar.constructor); // [Function: Foo]
    复制代码

4、配置对象的属性

  • 一、configurable: 若是为true表示能够修改与删除属性,若是为false就不能修改与删除

  • 二、enumerable: 若是为true表示为可枚举的可使用for..in

  • 三、value:指定属性的值

  • 四、writable:若是为true表示能够经过赋值语句修改对象属性

  • 五、get定义gettter函数

  • 六、set定义setter函数

  • 七、测试案例

    let obj1 = {};
    obj1.name = '哈哈';
    obj1.gender = '男';
    
    // 定义第三个属性
    Object.defineProperty(obj1, 'address', {
      configurable: false,
      enumerable: true,
      value: '深圳',
      writable: false,
    });
    
    console.log(JSON.stringify(obj1));
    
    for (let key in obj1) {
      console.log(`${key}===${obj1[key]}`);
    }
    复制代码

5、对象的一些扩展

  • 一、对象的私有属性

    function Foo() {
      let name;
      // 定义一个set方法赋值
      this.setName = (newVal) => name = newVal;
      // 定义一个get方法取值
      this.getName = () => name;
    }
    let foo = new Foo();
    foo.setName('哈哈');
    console.log(foo.getName());
    复制代码
  • 二、对象的setget方法

    // 在对象中get与set只是在属性前面加上了一个关键词,可是依然是属性的方式调用
    const obj1 = {
      name: '哈哈',
    
      get getName() {
        console.log('get方法');
        return this.name;
      },
    
      set setName(newVal) {
        this.name = newVal;
      }
    };
    
    console.log(obj1.getName);
    // obj1.setName = '张三';
    // console.log(obj1.getName);
    console.log(obj1.name);
    复制代码
  • 三、使用defineProperty定义私有属性

    function Foo() {
      let _age = 0;
      // 扩展一个属性
      Object.defineProperty(this, 'age', {
        get() {
          return _age;
        },
        set(newVal) {
          _age = newVal;
        }
      })
    }
    
    let foo = new Foo();
    console.log(foo.age);
    foo.age = 10;
    console.log(foo.age);
    复制代码
  • 四、使用setget进行数据的校验

    function Foo() {
      let _age = 0;
    
      Object.defineProperty(this, 'age', {
        get() {
          return _age;
        },
        set(newVal) {
          if (/\d+/.test(newVal)) {
            _age = newVal;
          } else {
            throw new TypeError('必须是数字');
          }
        }
      })
    }
    
    try {
      let foo = new Foo();
      console.log(foo.age);
      foo.age = 10;
      console.log(foo.age);
      foo.age = '哈哈';
    } catch (e) {
      console.log(e);
    }
    复制代码

6、关于原型的理解

  • 一、关于使用new关键词建立对象所发生的事情

    • 建立一个新对象
    • 将构造函数的做用域赋值给新对象(this指向新对象)
    • 执行构造函数的代码
    • 返回新的对象
  • 二、为何要使用构造函数的原型

    在使用构造函数建立对象的时候,每new一次就会建立一个对象,不一样的实例的同名函数是不相等的,所以建立不少重复的代码(每次new一个构造函数,上面的构造函数就会执行一次,就会在内存中开辟一块空间,指向新的堆对象,这样内存消耗比较大),咱们但愿代码尽量的复用,就须要原型

    // 普通的建立一个构造函数
    function Animal(name, age) {
      this.name = name;
      this.age = age;
      this.print = function() {
        console.log(`${this.name}====${this.age}`);
      }
    }
    // 使用原型
    function Animal(name, age) {
      this.name = name;
      this.age = age;
    }
    Animal.prototype.print = function() {
      console.log(`${this.name}====${this.age}`);
    }
    复制代码
  • 三、全部的对象都有一个constructor指向原型

  • 四、构造函数都有prototype指向原型

7、深刻理解类的继承(ES6前的版本)

在面向对象开发中继承的概念是,新对象复用旧对象上的属性和方法(有点相似拷贝Object.assign),相似生活中子继承父的财产及工具的概念

  • 一、一个构造函数的原型指定另一个构造函数

    function Person() {
    }
    
    // 定义原型
    Person.prototype.dance = function () {
      return 'dance function';
    };
    
    // 定义一个子类
    function Foo() {
    }
    Foo.prototype = Person.prototype;
    
    // 总结:采用这种方式来建立类的继承,只是地址指向(一个修改了,另一个也会随之修改)
    复制代码
  • 二、一个构造函数的原型指定另一个函数的实例对象

    function Person() {
    }
    
    // 定义原型
    Person.prototype.dance = function () {
      return 'dance function';
    };
    
    // 定义一个子类
    function Foo() {
    }
    
    // Foo构造函数的原型指向Person的实例对象
    Foo.prototype = new Person();
    let foo = new Foo();
    console.log(foo.dance());
    // 这样继承的方式会形成Foo的原型丢失,直接指定了Person
    console.log(foo.constructor);
    console.log(foo instanceof Foo);
    
    // 总结:采用这种方式实现继承:形成Foo的原型丢失,直接指定了Person
    复制代码
  • 三、修正方式二中constructor的指向

    function Person() {
    }
    Person.prototype.dance = function () {
      return 'dance function';
    }
    // 定义一个子类
    function Foo() {
    }
    Foo.prototype = new Person();
    let foo = new Foo();
    console.log(foo.constructor);
    // 修改Foo原型的constructor
    Object.defineProperty(Foo.prototype, 'constructor', {
      writable: false,
      enumerable: false,
      value: Foo,
    });
    let foo1 = new Foo();
    console.log(foo1.constructor);
    
    // 总结:修正`constructor`的指向
    复制代码

8、采用class的方式建立类

  • 一、建立一个类

    class Person {
      constructor(name, age) {
        this.name = name;
        this.age = age;
      }
    
      // 普通方法
      say() {
        return 'say...';
      }
    
      // 静态方法
      static talk() {
        console.log(this);
        return '我是静态方法';
      }
    }
    
    let p = new Person('哈哈', 20);
    console.log(Person.talk());
    复制代码
  • 二、实现类的继承

    class Animal {
      constructor(name) {
        this.name = name;
      }
    
      call() {
        return '在叫';
      }
    }
    
    class Dog extends Animal {
      constructor(name, age) {
        super(name);
        this.age = age;
      }
    
      // 重写父类的方法
      call() {
        return `${this.name}在叫`;
      }
    }
    
    let dog = new Dog('大黄狗', 3);
    
    console.log(dog.call());
    复制代码
  • 三、使用setget方法

    class Person {
      constructor() {
        this.name = '哈哈';
      }
    
      set setName(newVal) {
        this.name = newVal;
      }
    
      get getName() {
        return this.name;
      }
    }
    
    let p = new Person();
    console.log(p.getName);
    p.setName = '张三';
    console.log(p.getName);
    复制代码

9、Proxy的使用


ProxyES6中新增的对象,使用方式Proxy(目标对象,代理的对象)

主要有以下属性

  • get(target, propKey, receiver):拦截对象属性的读取,好比√proxy.foo和proxy['foo']√。

  • set(target, propKey, value, receiver):拦截对象属性的设置,好比proxy.foo = vproxy['foo'] = v,返回一个布尔值。

  • has(target, propKey):拦截propKey in proxy的操做,返回一个布尔值。

  • deleteProperty(target, propKey):拦截delete proxy[propKey]的操做,返回一个布尔值。

  • ownKeys(target):拦截Object.getOwnPropertyNames(proxy)、Object.getOwnPropertySymbols(proxy)、Object.keys(proxy)、for...in循环,返回一个数组。该方法返回目标对象全部自身的属性的属性名,而Object.keys()的返回结果仅包括目标对象自身的可遍历属性。

  • getOwnPropertyDescriptor(target, propKey):拦截Object.getOwnPropertyDescriptor(proxy, propKey),返回属性的描述对象。

  • defineProperty(target, propKey, propDesc):拦截Object.defineProperty(proxy, propKey, propDesc)、Object.defineProperties(proxy, propDescs),返回一个布尔值。

  • preventExtensions(target):拦截Object.preventExtensions(proxy)`,返回一个布尔值。

  • getPrototypeOf(target):拦截Object.getPrototypeOf(proxy)`,返回一个对象。

  • isExtensible(target):拦截Object.isExtensible(proxy),返回一个布尔值。

  • setPrototypeOf(target, proto):拦截Object.setPrototypeOf(proxy, proto),返回一个布尔值。若是目标对象是函数,那么还有两种额外操做能够拦截。

  • apply(target, object, args):拦截 Proxy 实例做为函数调用的操做,好比proxy(...args)、proxy.call(object, ...args)、proxy.apply(...)

  • construct(target, args):拦截 Proxy 实例做为构造函数调用的操做,好比new proxy(...args)

  • 一、使用案例

    let targetObj = {name: '哈哈'};
    
    const proxy = new Proxy(targetObj, {
      set(target, key, val) {
        console.log(target);
        console.log(key);
        console.log(val);
        target[key] = val;
      },
      get(target, key) {
        console.log(target);
        console.log(key);
        return key in target ? target[key] : '不存在这个key';
      },
      // 使用in的时候调用
      has(target, key) {
        console.log(target, key)
        if (target.hasOwnProperty(key)) {
          return true;
        } else {
          return false;
        }
      },
      deleteProperty(target, key) {
        if (target.hasOwnProperty(key)) {
          return true;
        } else {
          return false;
        }
      }
    });
    复制代码
  • 二、代理方法

    let targetObj = function () {
      return '目标函数';
    };
    
    let proxy = new Proxy(targetObj, {
      apply(target, ctx, args) {
        console.log(target());
        console.log(ctx);
        console.log(args);
        return 'apply 函数';
      }
    });
    
    proxy(12, 20);
    复制代码
相关文章
相关标签/搜索