javaScript-对象

面向对象编程

  let user = {
    name: "小孙吗",
    grade: [
      { name: "js", score: 99 },
      { name: "docker", score: 76 }
    ],
    average() {
      let total = this.grade.reduce((t, l) => t + l.score, 0);
      return `${this.name}的平均成绩是: ${total / this.grade.length}`;
    }
  };
  // console.log(user);
  console.log(user.average());

属性的基本操作方法

    let user = {
      name: "sss",
      "my age": 18
    };
    console.log(user.name);
    console.log(user["name"]);
    console.log(user["my age"]);
    for (const key in user) {
      console.log(user[key]);
    }
    user.age = 19;
    user.get = function() {
      return `${this.name}的年龄是${this.age}`;
    };
    console.log(user.get());
    delete user.age;
    console.log(user.get());
  • 点语法
  • [‘我是各种字符串’]
  • [‘我是变量’]

解构赋值新增特性

  let user = { name: "ss", age: 18 };
  const { name } = user;
  console.log(name);

严格模式中解构的差异

严格模式必须加const

    "use strict";
    const { name, age } = { name: "sss", age: 23 };
    console.log(name, age);

解构操作的简写形式

  let name = "sss",
    url = "www.bai";
  let opt = { name, url };
  console.log(opt);

多层对象的解构操作

  let kk = {
    name: "sss",
    lesson: {
      title: "javascript"
    }
  };
  let { name, lesson: { title } } = kk;
  console.log(name, title);

利用默认值解决undefined报错

let { width = 200, height = 100, backgroundColor = "red" } = options;

函数参数解构技巧

  function hd(name, { sex, age }) {
    console.log(name, sex, age);
  }
  hd("aaa", { sex: "男", age: 18 });

对象的添加删除

添加:

  let aa = {};
  aa.name = "aaa";
  hd["age"] = 18;

删除:

  delete aa.name;

对象与原型链属性检测实例

  1. 检查当前对象
    a.hasOwnProperty(“s”)
  2. 检查对象(包含原型链)
    console.log(“url” in a);

计算属性与assign使用

  1. 可以动态设置对象的键名
  2. Object.assign(a,b);可以将两个对象合并

遍历操作以及对象的一些方法

Object.keys(ss) //获取键值
Object.values(ss) //获取value
Object.entries(ss) //获取整体信息以数组展现

遍历用for in
for of 遍历实现方法:

  let hd = {
    name: "ss",
    year: "2010"
  };
  for (const [key, value] of Object.entries(hd)) {
  console.log(value);
  }

对象的浅拷贝多种操作方法

只能拷贝一层对象,对于对象内部套对象则不再适用。

1.let obj = { ...ss};

2.let obj = Object.assign({}, ss);

3.for (const key in ss) {
    obj[key] = hd[key] + "111";
}

4.let cms = {
    name: ss.name
};

深拷贝多层次分析

由于对象是引用存储的,所以当嵌套复制只会直接拷贝内存地址,改变子对象中的子对象,父对象中的子对象也会发生改变。
方法:
多层递归(数组只能实现一层)
一般借助各种库

  let data = {
    name: "sss",
    user: {
      name: "hdcms"
    },
    arr: []
  };
  function copy(obj) {
    let res = obj instanceof Array ? [] : {};
    for (const [k, v] of Object.entries(obj)) {
      res[k] = typeof v == "object" ? copy(v) : v;
    }
    return res
  }
  let hds = copy(data);
  hds.arr.push("abc");
  console.log(JSON.stringify(hd, null, 2));
  console.log(JSON.stringify(data, null, 2));

使用工厂函数创建对象

  function user(name, age) {
    return {
      name,
      age,
      show() {
        console.log(this.name + `-sss.com`);
      },
      info() {
        console.log(`${this.name}的年龄是${this.age}`);
      }
    };
  }

使用构造函数创建windows对象

系统会自动return 但是如果return了返回啥就是啥
ps:这不就是普通函数然后new时候让它有了return么

    "use strict";
    function User(name) {
      this.name = name;
      this.show = function() {
        console.log(this);
        // console.log(this.name);
      };
      // return this;
      // return {};
    }

面向对象的封装与抽象

利用let 使外部无法影响到内部,内部互相访问通过闭包来实现,这种方法就是抽象

  function User(name, age) {
    let data = { name, age };
    let info = function () {
      return data.age > 50 ? "老年" : "青年";
    };
    this.show = function () {
      console.log(data.name + info());
    };
  }

对象属性的值

通过

Object.getOwnPropertyDescriptor(user, "name")

Object.getOwnPropertyDescriptors(user)

获取属性特征

{
  "value": "aa",//值
  "writable": true,//是否可写
  "enumerable": true,//是否可遍历
  "configurable": true //是否可被删除/可配置属性(设置以上属性)
}

设置属性:Object.definePropertie
批量设置:Object.defineProperties

  Object.defineProperties(user, {
    name: {
      value: "sss",
      writable: true,
      enumerable: false,
      configurable: true
    },
    age: {
      value: "sss",
      writable: true,
      enumerable: true,
      configurable: true
    }
  });

设置不允许添加属性API

  // Object.preventExtensions(user);//设置
  if (Object.isExtensible(user)) {//判断是否设置了不允许添加
    user.site = "sss";
    console.log(user);
  }

封闭对象的API

  Object.seal(user);//设置
  if (!Object.isSealed(user)) {//检测是否封闭
    user.site = "sss";
    delete user.name;
  }

冻结对象API特性(最常用)

只读:不允许添加修改以及对对象内部做一些设置

Object.freeze(user);

使用访问器保护数据

  "use strict";
  const user = {
    data: { name: "sam", age: 10 },
    set age(value) {
      if (typeof value != "number" || value < 10 || value > 100) {
        throw new Error("年龄格式错误");
      }
      this.data.age = value;
    },
    get age() {
      return this.data.age + "岁";
    }
  };

使用访问器伪造属性操作

使用方便,修改无效

  "use strict";
  let Lesson = {
    lists: [
      { name: "js", price: 100 },
      { name: "mysql", price: 212 },
      { name: "vue.js", price: 98 }
    ],
    get total() {
      return this.lists.reduce((t, l) => t + l.price, 0);
    }
  };

使用访问器批量设置属性

  "use strict";
  const web = {
    name: "sss",
    url: "aaa",
    get site() {
      return `${this.name}的网址是${this.url}`;
    },
    set site(value) {
      [this.name, this.url] = value.split(",");
    }
  };
  web.site = "开源产品,www.sss.com";

TOKEN的读写处理(可以自己在项目中尝试一下)

直接用点的形式来改写token处理逻辑(或者其他用途,访问器真不错哦)

  "use strict";
  //token
  let Request = {
    set token(content) {
      localStorage.setItem("token", content);
    },
    get token() {
      let token = localStorage.getItem("token");
      if (!token) {
        alert("请登录");
      }
      return token;
    }
  };
  Request.token = "3248989239823kldskjklsd";
  console.log(Request.token);

访问器的优先级(放在data中的方式以及私有化)

利用data隔绝、利用symbol使得data唯一

  "use strict";
  const DATA = Symbol();
  const user = {
    [DATA]: { name },
    age: 10,
    set name(value) {
      this[DATA].name = value;
    },
    get name() {
      return this[DATA].name;
    }
  };
  user.name = "sss";

在class语法糖中定义访问器

  "use strict";
  const DATA = Symbol();
  class User {
    constructor(name, age) {
      this[DATA] = { name, age };
    }
    get name() {
      return this[DATA].name;
    }
    set name(value) {
      if (value.trim() == "" || value.length > 20) {
        throw new Error("用户名不合法");
      }
      this[DATA].name = value;
    }
    get age() {
      return this[DATA].age;
    }
    set age(value) {
      this[DATA].name = age;
    }
  }

什么是Proxy代理拦截

将整个对象代理给别人处理(类似找中介买房子)
内置函数参数:整个proxy、键(如果是数组就是索引)、值

  "use strict";
  const hd = { name: "sss" };
  const proxy = new Proxy(hd, {
    get(obj, property) {
      // console.log(obj);
      return obj[property];
    },
    set(obj, property, value) {
      obj[property] = value;
      return true;
    }
  });
  console.log(proxy.name);
  proxy.name = "aaa";
  console.log(proxy.name);
  console.log(proxy);

使用代理Proxy控制函数

参数:(函数、上下文、函数的参数)

  function factorial(num) {
    return num == 1 ? 1 : num * factorial(num - 1);
  }
  let proxy = new Proxy(factorial, {
    apply(func, obj, args) {
      console.time("run");
      func.apply(this, args);
      console.timeEnd("run");
    }
  });
  proxy.apply({}, [1000]);

数组使用代理拦截操作

参数:(原数组、key)

  const lessons = [
    {
      title: "媒体查询响应式布局",
      category: "css"
    },
    {
      title: "FLEX模型",
      category: "css"
    },
    {
      title: "MYSQL多表查询随意操作",
      category: "mysql"
    }
  ];
  let proxy = new Proxy(lessons, {
    get(array, key) {
      const title = array[key].title;
      const len = 10;
      array[key].title =
        title.length > len ? title.substr(0, len) + ".".repeat(3) : title;
      return array[key];
    }
  });

双向绑定的实现

  1. 创建一个空对象用于存放数据
  2. 其他几个需要双向绑定的与这个空对象进行绑定
  3. 改变后将数据存放于对象中同时触发set(这里Vue用的是get与set)
  4. 将改变后的数据设置于其他绑定的模块
    function View() {
      let proxy = new Proxy(
        {},
        {
          get(obj, property) {},
          set(obj, property, value) {
            // console.log(value);
            // console.log(property);
            document
              .querySelectorAll(`[v-model="${property}"]`)
              .forEach(item => {
                item.value = value;
              });
            document
              .querySelectorAll(`[v-bind="${property}"]`)
              .forEach(item => {
                item.innerHTML = value;
              });
          }
        }
      );
      this.init = function() {
        const els = document.querySelectorAll("[v-model]");
        els.forEach(item => {
          item.addEventListener("keyup", function() {
            proxy[this.getAttribute("v-model")] = this.value;
          });
        });
      };
    }
    new View().init();

表单验证(这个自己封装一下封装好了在这写好地址)

"use strict";
  class Validate {
    max(value, len) {
      return value.length <= len;
    }
    min(value, len) {
      return value.length >= len;
    }
    isNumber(value) {
      return /^\d+$/.test(value);
    }
  }
  function ProxyFactory(target) {
    return new Proxy(target, {
      get(target, key) {
        return target[key];
      },
      set(target, key, el) {
        const rule = el.getAttribute("rule");
        const validate = new Validate();
        let state = rule.split(",").every(rule => {
          const info = rule.split(":");
          return validate[info[0]](el.value, info[1]);
        });
        el.classList[state ? "remove" : "add"]("error");
        return true;
      }
    });
  }
  const proxy = ProxyFactory(document.querySelectorAll("[validate]"));
  proxy.forEach((item, i) => {
    item.addEventListener("keyup", function () {
      proxy[i] = this;
    });
  });

JSON.stringify

参数:(需要转换的对象、需要保留的值(全部就是null)、首行缩进)
可以在对象中定义json默认返回哪些

  let hd = {
    title: "aa",
    url: "sss.com",
    teacher: {
      name: "ddd"
    },
    toJSON: function () {
      return {
        title: this.title,
        teacher: this.teacher.name
      };
    }
  };
  let json = JSON.stringify(hd, null, 2);
  console.log(json);

JSON.parse中的参数

  let ac = {
    title: "aaa",
    url: "sss.com",
    teacher: {
      name: "vvv"
    }
  };
  let json = JSON.stringify(ac, null, 2);
  console.log(json);

  let obj = JSON.parse(json, (key, value) => {
    if (key == "title") {
      value = "[你好]-" + value;
    }
    return value;
  });
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值