想品客老师的第八天:对象(上)

前置在这里

目录

函数式VS面向对象

属性的基本操作

增删改查

增、改

对象的引用传址

深浅拷贝

展开语法在对象里的使用

对象解构

严格模式里解构的差异

解构操作的简写形式与变量解构

多层嵌套也可以用

解构的默认值

解构可以合并参数

解构作为函数参数的使用

对象的属性检测

计算属性与assign使用

遍历与dom操作

工厂函数创建对象

构造函数创建对象

面向对象的封装与抽象


前置在这里

函数式VS面向对象

函数式编程改良->面向对象式编程

这是函数式

 let name = '荷叶饭'
        let grade = [
            { name: 'js', score: 99 },
            { name: 'docker', score: 96 }
        ]
        function average(grade, name) {
            let total = grade.reduce((last, next) => last + next.score, 0)
            return `${name}的平均成绩是:${total / grade.length}`
        }
        console.log(average(grade,name))//荷叶饭的平均成绩是:97.5

这是面向对象式:

   let user = {
            name: '荷叶饭',
            grade: [
                { name: 'js', score: 99 },
                { name: 'docker', score: 96 }
            ],
            average() {//省去参数的传递
                let total = this.grade.reduce((last, next) => last + next.score, 0)//直接使用this指针
                return `${this.name}的平均成绩是:${total / this.grade.length}`
            }
        }
        console.log(user.average())//荷叶饭的平均成绩是:97.5

减少意大利面条式的编程结果

属性的基本操作

增删改查

【.】和【[]】两种方式访问属性,属性名是个字符串的时候可以用【[]】中括号:

  let user={
            name:'荷叶饭',
            'my age':19
        }
        console.log(user['my age'])//19

用【.】更普遍

增、改

对已有的就是改,对没有的就是添加

let hd={}
hd.name='后盾人'
hd['age']=18
console.log(hd.age)//18
hd.age=199
console.log(hd.age)//199

delete删除:

let hd={}
hd.name='后盾人'
hd['age']=18
console.log(hd.age)//18
hd.age=199
console.log(hd.age)//199
delete(hd.age)//删除
console.log(hd.age)//undefined

对象的引用传址

在js里数组和对象等都为引用类型,而深浅拷贝只适用于引用类型的数据,在值类型的数据里不作深浅拷贝的区分

深浅拷贝

深浅拷贝、传值传址写在这里

浅拷贝的几种方式:展开语法、assign、普通赋值

深拷贝:递归

     const obj = {
            uname: '荷叶饭',
            age: 18,
            friends: {
                EPI: '励志轩'
            },
            hobby: ['乒乓球', '羽毛球']
        }
        const o = {}
        function deepCopy(newObj, oldObj) {
            for (let k in oldObj) {
                if (oldObj[k] instanceof Array) {
                    //如果是数组
                    //数组本身也属于对象,所以一定把筛选数组的if写在前面
                    newObj[k] = []
                    deepCopy(newObj[k], oldObj[k])
                } else if (oldObj[k] instanceof Object) {
                    //如果是对象
                    newObj[k] = []
                    deepCopy(newObj[k], oldObj[k])
                } else {
                    //值类型情况
                    newObj[k] = oldObj[k]
                }
            }
        }
        deepCopy(o, obj)
        console.log(o)
        o.age = 20
        o.hobby[0] = '游泳'
        o.friends.EPI = '荷月'
        console.log(obj)

展开语法在对象里的使用

使用展开语法合并参数:

  let user = {
        name: '荷叶饭',
        'my age': 19
    }
    let hd={...user,gender:'女'}
    console.log(hd)//{name: '荷叶饭', my age: 19, gender: '女'}

在函数里使用对象的展开语法:

function upload(p){
    let config={
        type:'*.jpeg,*.png',
        size:10000//默认属性
    }
    config={...config,...p}//同属性名,后面的会覆盖前面的
    console.log(config)//{type: '*.gif', size: 99}
}
upload({type:'*.gif',size:99})//用户传入自己的属性

对象解构

展开语法是对对象或数组的批量处理,解构是对对象或数组结构的批量处理

  let user = { name: "荷叶饭", age: 19 }
            // console.log(user);   
            //const { name:name, age:age } = user//如果新属性名和旧属性名一样
            const { name, age } = user//可以简写成这样
            console.log(age)//19

函数的返回值是对象,也可以使用解构语句:

function hd(){
    return { name: "荷叶饭", age: 19 }
}
let {name,age}=hd()
console.log(name,age)//荷叶饭,19

函数传参的时候也可以这么写:

function user({name,age}) {
    console.log(name,age)
}
user({ name: "荷叶饭", age: 19 })//荷叶饭,19

严格模式里解构的差异

严格模式要写声明语句:let或const都行,反正得写:

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

在普通模式下,如果变量没有被显式声明,JavaScript 会隐式地将其声明为全局变量。因此,在普通模式下,name 和 age 会被隐式声明为全局变量,代码不会报错。

不加括号时,JavaScript 会将 { ... } 解析为一个代码块,而不是对象解构赋值

 ({ name, age } = { name: "向军", age: 23 })//严格模式报错,得加括号
            console.log(name, age);

解构操作的简写形式与变量解构

参数一样可以简写,前面说过了:

let web = { name: "后盾人", url: "houdunren.com" };
            let { name, url } = web;
            console.log(name, url);

数组里的变量解构如果只想取一个值,得空着:

   let arr = ["后盾人", "houdunren.com"]
            let [, b] = arr//不需要前面的参数可以不写
            console.log(b)//houdunren.com

对象因为是以键值对存储的,所以如果键名一样可以只写要的属性:

let web = { name: "后盾人", url: "houdunren.com" };
     let { url } = web;
     console.log(url);

对普通变量也可以这么用:

  let name = "后盾人",
                url = "houdunren.com";
            // console.log({ name:name, url:url })简写的本质
            let opt = { name, url }
            console.log(opt)//{name: '后盾人', url: 'houdunren.com'}

多层嵌套也可以用

let hd = {
      name: "后盾人",
      lesson: {
        title: "javascript"
      }
    };
    let {
      name,
      lesson: { title }
    } = hd;
    console.log(name, title);

解构的默认值

数组里接收的参数比较多可以给多的那个添加默认值:

    let arr = ["后盾人", "houdunren.com"];
    let [a, b, c = "hdcms"] = arr;//当第三个参数可能没有的时候,给他个默认值
    console.log(a, b, c);//后盾人 houdunren.com hdcms

对象也可以用过:

let user = { name: "后盾人", url: "houdunren.com"};
    let { url, name, title = "hdcms" } = user;
    console.log(name, url, title)//后盾人 houdunren.com hdcms

let user = { name: "后盾人", url: "houdunren.com", title: "开源系统" };
    let { url, name, title = "hdcms" } = user;
    console.log(name, url, title)//后盾人 houdunren.com 开源系统

解构可以合并参数

那已有的参数合并给变量opt:

function createElement(opt={}){//opt默认值为{}
    let {width=200,height=100,backgroundColor='red'}=opt
    console.log(width,height,backgroundColor)
}
createElement()//200 100 'red'

实操一下:

    function createElement(options = {}) {
        let { width = 200, height = 100, backgroundColor = "red" } = options;
        // console.log(width, height, backgroundColor);
        const div = document.createElement("div");
        div.style.width = width + "px";
        div.style.height = height + "px";
        div.style.backgroundColor = backgroundColor;
        document.body.appendChild(div);
    }
    createElement({ width: 60, height: 30, backgroundColor: "green" });

如果自己不写参数,就是用默认值:

 function createElement(options = {}) {
        let { width = 200, height = 100, backgroundColor = "red" } = options;
        // console.log(width, height, backgroundColor);
        const div = document.createElement("div");
        div.style.width = width + "px";
        div.style.height = height + "px";
        div.style.backgroundColor = backgroundColor;
        document.body.appendChild(div);
    }
    createElement({ width: 60});

解构作为函数参数的使用

解构就是结构相似就能承载:

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

对象的属性检测

孩子们原型对象和对象原型还在追我

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

一个属性可能一个对象有,像这样:

 let hd = { name: "后盾人" };
            let arr = ["houdunren.com", "hdcms"];
            console.log(arr.hasOwnProperty("length"));//true,arr实例对象里有length属性
            console.log(arr.hasOwnProperty("concat"));//false,arr实例对象没有concat属性

如果想看他的原型链上有没有,可以这么写:

console.log("concat" in arr);//true,在父级找到
            console.log("length" in arr);//true,在本级找到
  let a = {
        name: "后盾人"
    };
    let b = {
        url: "houdunren.com"
    };
    Object.setPrototypeOf(a, b);//设置b为a的原型对象
    console.log(a);
    console.log(a.hasOwnProperty("url"));//a里面是否包含url,a不包含,a的父级包含,所以为false
    console.log("url" in a);//a的父亲包含,true

一个检测配置的demo:

 function oss(options) {
      if (!options.hasOwnProperty("host")) {
        throw new Error("必须设置主机地址");
      }
    }
    oss({ user: "admin" });

计算属性与assign使用

这里的 name 是一个变量,其值为 "title",因此 hd[name] 等价于 hd["title"]

 let hd = {};
    let name = "title";
    hd[name] = "后盾人";
    console.log(hd.title);//后盾人

assign合并两个对象:

    const lessons = [
        {
            title: "媒体查询响应式布局",
            category: "css"
        },
        {
            title: "FLEX 弹性盒模型",
            category: "css"
        },
        {
            title: "MYSQL多表查询随意操作",
            category: "mysql"
        }
    ];
    let res = lessons.reduce((obj, cur, index) => {
        obj[`${cur["category"]}-${index + 1}`] = cur;
        return obj;
    }, {});
    // console.log(res);
    console.log(JSON.stringify(res, null, 2));

    // let hd = Object.assign({ a: 1 }, { b: 2 });
    // console.log(hd);
    // jQuery.extend()  lodash
    function upload(params) {
        let options = {
            size: 19999
        };
        options = Object.assign(options, params);//合并两个对象
        console.log(JSON.stringify(options, null, 2));
    }
    upload({ size: 99, type: "jpeg" });

遍历与dom操作

for in循环:

let hd = {
        name: "后盾人",
        year: "2010"
    };
    for (const key in hd) {
      console.log(hd[key]);
    }

key就是键名,hd[key]就是值

for of不行,for of操作的是可迭代对象,这种对象迭代不了

  for (const iterator of hd) {
      console.log(iterator);
    }

会报错

但是键名可以迭代:

   for (const iterator of Object.values(hd)) {
            console.log(iterator);
        }

entries也可以迭代:

   for (const iterator of Object.entries(hd)) {
                console.log(iterator);
            }

可以发现返回的是个数组

可以借助这个做节点操作:

   let lessons = [
        { name: "js", click: 999 },
        { name: "node", click: 127 }
    ];
    let ul = document.createElement("ul");
    for (const lesson of lessons) {
        let li = document.createElement("li");
        li.innerHTML = `课程:${lesson.name},点击数:${lesson.click}`;
        ul.appendChild(li);
    }
    document.body.appendChild(ul);

三小时的课我与你势不两立

工厂函数创建对象

工厂函数是一个普通函数,它通过返回一个对象来创建实例。工厂函数不需要使用 new 关键字。

function user(name){
    return {
        name,
        show:function(){
            console.log(this.name+`-孩子们今天是除夕`)
            
        }
    }
}
let hyf=user('荷叶饭')
hyf.show()
let lzx=user('励志轩')
lzx.show()

如果想变动的话,变动工厂函数,这两个对象也会随之改变:

function user(name){
    return {
        name,
        show:function(){
            console.log(this.name+`-孩子们今天是除夕,我还在学js,这辈子有了`)
            
        }
    }
}
let hyf=user('荷叶饭')
hyf.show()
let lzx=user('励志轩')
lzx.show()

构造函数创建对象

构造函数是 JavaScript 中一种传统的创建对象的方式。它通过 new 关键字调用,并返回一个新的对象。

命名大驼峰

function User(name){
    this.name=name
    this.show=function(){
        console.log(this.name)
}
//return this,这里return this可以省略,但是这里的return会决定使用构造函数创建的对象
}
let hyf=new User('荷叶饭')
console.log(hyf)

还有一个历史遗留的问题:当你把构造函数当一个普通函数调用的时候,this指向window,调用的属性或方法也可能调成window的属性和方法

在这种情况下使用严格模式,会报undefined,因为严格模式怕你无意识修改window的属性

数据也可以拿构造函数构建,他们的constructor指向的是他们的构造函数,js万物皆对象,皆有构造函数:

    let s = new String("houdunren");
    let n = new Number(1);
    let o = new Object();
    let b = new Boolean(true);

还有正则表达式、日期对象、函数也可以拿构造函数创建

  let User = new Function(
        "name",
        `
      this.name = name;
      this.show = function(){
        console.log(this.name+'是能过构造函数Function创建的');
      }
    `
    );
    let xj = new User("函数");
    xj.show();

太长了,分两篇写

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值