sugar_coffee

sugar_coffee 查看完整档案

上海编辑  |  填写毕业院校  |  填写所在公司/组织填写个人主网站
编辑
_ | |__ _ _ __ _ | '_ \| | | |/ _` | | |_) | |_| | (_| | |_.__/ \__,_|\__, | |___/ 该用户太懒什么也没留下

个人动态

sugar_coffee 发布了文章 · 今天 14:46

ES6中常用的对象方法:Object.keys()、Object.values() ...

1. Object.assign()

Object.assign() 用于将所有可枚举属性的值从一个或多个源对象,复制到目标对象。

语法:Object.assign(obj, ...sources)

  • obj:目标对象
  • sources:源对象,可以是多个
  • 返回目标对象

复制一个对象

const obj = { a: 1 }
const copy = Object.assign({}, obj)
console.log(copy); // { a: 1 }

合并对象

const obj1 = { a: 1, b: 2 }
const obj2 = { b: 3, c: 4 }
const obj3 = { c: 5, d: 6 }
​
const obj = Object.assign(obj1, obj2, obj3)
console.log(obj) // {a: 1, b: 3, c: 5, d: 6}

注:如果目标对象与源对象有同名属性,则后面的属性会覆盖前面的属性;如果多个源对象有同名的属性,则后面的源对象会覆盖前面的。

对象的深拷贝

通过 Object.assign() 我们可以很快的实现对象的复制,然而这只是一个浅拷贝,因为 Object.assign() 方法拷贝的是可枚举属性值,如果源对象的属性值是一个对象的引用,那么该方法也只会复制其引用。

// 浅拷贝
let o1 = {
    a: 0,
    b: { c: 0 }
}
const o2 = Object.assign({}, o1)
o1.b.c = 1 
console.log(o2.c) // 1

那么,我们怎么实现一个对象的深拷贝呢?
如果不考虑保留内置类型,最快速的方法是通过JSON.stringify() 将该对象转换为 json 字符串表现形式,然后再将其解析回对象。

// 深拷贝:方法一
let obj1 = { a: 0 , b: { c: 0}}
let obj2 = JSON.parse(JSON.stringify(obj1))
obj1.a = 4 
obj1.b.c = 4 

console.log(obj1)   // { a: 4, b: { c: 4}} 
console.log(obj2)   // { a: 0, b: { c: 0}}

还可以通过递归的方法实现深拷贝

// 深拷贝:方法二
const obj = {
    name: 'andy',
    age: 18,
    info: {
        gender: 'male',
        schoole: 'NEWS' 
    },
    color: ['pink', 'yellow']
} 
function deepCopy(obj){
    let o = {} 
    for(let k in obj) {  // 此处的for...in方法可以使用Object.keys(obj).map(k =>{....}) 替换
        // 1.获取属性值
        var item = obj[k]; // 2.判断属性值属于哪种数据类型
        if(item instanceof Array) { // 是否是数组
            o[k] = []
            deepCopy(o[k], item)
        } else if(item instanceof Object) { // 是否是对象
            o[k] = {}
            deepCopy(o[k], item)
        } else { // 简单数据类型
            o[k] = item
        }
    } return o
}
const newObj = deepCopy(obj)
console.log(newObj)

此外,还可以通过structured clone结构化克隆算法,有兴趣的自行查阅。

2. Object.create() 创建一个新对象

语法:Object.create(proto)

  • proto:新创建对象的原型对象
  • 返回一个新对象

使用:

const person = {
    isHuman: false,
    printIntroduction: function() {
        console.log(`My name is ${this.name}. Am I human? ${this.isHuman}`);
    }
}

// Object.create() 方式创建对象
const me = Object.create(person)
console.log(me)   // {}
me.name = 'Matthew'   // "name" is a property set on "me", but not on "person"
me.isHuman = true   // inherited properties can be overwritten
me.printIntroduction()   // My name is Matthew. Am I human? true
console.log(me.__proto__ === person)   //true

​// 通过new Object()方式创建对象
const me = new Object(person)
console.log(me)   // {isHuman: false, printIntroduction: ƒ}
me.name = 'Matthew' 
me.isHuman = true 
console.log(me)   // {isHuman: true, name: "Matthew", printIntroduction: ƒ}

Object.create() 可以实现对象的继承,可以通过对象实例的 __proto__ 属性访问原型链上的属性。

new Object() 方法创建的对象,给对象原型添加属性和方法则需要通过构造函数或者类。

function Person(name, age){ 
    this.name=name this.age=age
}
Person.prototype.sayHi = function(){
    console.log(this.name)
}

let p = new Person('jack', 20)
console.log(p.sayHi()) // jack
console.log(p.__proto__ === Person.prototype) // true

3. Object.defineProperty()

Object.defineProperty() 添加或修改现有属性,并返回该对象。

语法:Object.defineProperty(obj, prop, description)

  • obj:必需。目标对象

  • prop:必需。需定义或修改的属性的名字

  • descriptor:必需。目标属性所拥有的特性,以对象形式{}书写。

    1. value:设置属性的值,默认为 undefined
    2. writable:值是否可以重写,true | false,默认为 false
    3. enumerable:目标属性是否可以被枚举,true | false,默认为 false
    4. configurable:目标属性是否可以被删除或是否可以再次修改特性,true | false,默认为 false
const obj = {
    id: 1,
    name: 'phone',
    price: '$599' 
}
Object.defineProperty(obj, 'num', {
    value: 100,
    enumerable: false 
})

console.log(obj)   // {id: 1, name: "phone", price: "$599", num: 100}
console.log(Object.keys(obj))   // ["id", "name", "price"]

4. Object.entires()

Object.entires() 遍历并返回该对象可枚举属性的键值对数组

语法:Object.entires(obj)

  • 返回对象可枚举属性的键值对数组
const obj = {
    a: 'apple',
    b: 'bar' 
}
console.log(Object.entries(obj)) // [ ['a', 'apple'], ['b', 'bar'] ]

for (const [key, value] of Object.entries(obj)) {
    console.log(`${key}: ${value}`) //"a: somestring"  "b: 42"
}

Object.entries(obj).forEach(([key, value]) => {
    console.log(`${key}: ${value}`) // "a: somestring", "b: 42"
})

5. Object.keys() 

Object.keys() 用于获取对象自身所有可枚举的属性

语法:Object.keys(obj)

  • 效果类似于 for...in
  • 返回一个由属性名组成的数组
const obj = {
    id: 1,
    name: 'phone',
    price: '$599',
    num: 100 
}

const objKeys = Object.keys(obj);
console.log(objKeys)   //['id', 'name', 'price', 'num']
​
const arr = ['a', 'b', 'c']
const arrKeys = Object.keys(arr)
console.log(arrKeys)   //['0', '1', '2']

补充:如果只要获取对象的可枚举属性,可用Object.keys或用for...in循环(for...in循环会得到对象自身的和继承的可枚举属性,可以使用 hasOwnProperty()方法过滤掉)

6. Object.values()

Object.values() 获取对象自身所有可枚举的属性值

语法:Object.values(obj)

  • 返回一个由属性值组成的数组
const obj = {
    id: 1,
    name: 'phone',
    price: '$599',
    num: 100 
}

const objValues = Object.values(obj);
console.log(objValues); //[1, 'phone', '$599', '100']

附:对象的所有属性和方法

image

查看原文

赞 0 收藏 0 评论 0

sugar_coffee 回答了问题 · 今天 14:31

解决vue添加的监听事件无法移除

使用了 keep-alive, 离开A页面时,因为组件没被销毁,被缓存起来了,所以不会调用 beforeDestroy 和 destroyed 钩子。
在 keep-alive 中创建的组件,会多出两个生命周期的钩子: activated 与 deactivated:
activated:在 keep-alive 组件激活时调用
deactivated:在 keep-alive 组件停用时调用

当首次进入组件时:

  • beforeRouteEnter > beforeCreate > created > mounted > activated > ... ... > beforeRouteLeave > deactivated

再次进入组件时:

  • beforeRouteEnter > activated > ... ... > beforeRouteLeave > deactivated

所以可以通过组件内导航守卫结合activated,deactivated来设置添加或取消监听

关注 5 回答 4

sugar_coffee 回答了问题 · 10月27日

解决js怎么判断字符串里是否有某个数字。

用字符串的includes()方法:

var a = "2, 3, 4, 5, 6, 7, 11, 22, 33, 44";
console.log(a.includes(2))

关注 5 回答 4

sugar_coffee 回答了问题 · 10月22日

请教各位大佬element中table组件如何宽度自适应

el-table外面再包裹一层布局容器,el-main、el-container

关注 2 回答 3

sugar_coffee 回答了问题 · 10月21日

element ui label长度更改失效

:label-width="'180px'"

关注 3 回答 1

sugar_coffee 回答了问题 · 10月21日

解决清除浏览器数据,vuex会默认state里的初始化数据,怎么解决?

当你点击清除浏览器数据,如果勾选了Cookie及其他网站数据,cookie、localStorage、sessionStorage下缓存的数据都会被清除。
比如在系统的登录跳转做了登录用户信息的验证(导航守卫),这时一般是会退出当前登录系统的,然后再重新登录就可以了

关注 3 回答 4

sugar_coffee 回答了问题 · 10月20日

解决不使用三元运算符和 if ,如何优雅地切换变量的值?

const aa = new Map([
  ['1', 2],
  ['2', 1]
])

const val = (key) => {
  return aa.get(key)
}
console.log(val('1'))

关注 10 回答 11

sugar_coffee 发布了文章 · 10月20日

vue-router 路由传参,刷新页面参数丢失

常见场景:点击列表的详情,跳转到详情内页,在内页根据传递的参数获取详情数据。

image

路由传参一般有如下几种方式,下面主要介编程式导航 router.push 的传参方式:

方法一:通过 params 传参

路由配置如下:

{ 
    path: '/detail/:id',  //若id后面加?代表这个参数是可选的
    name: 'detail', 
    component: Detail 
}
  • 通过 $router.push 中 path 携带参数的方式

    // 列表中的传参
    goDetail(row) { this.$router.push({
            path: `/detail/${row.id}`
        })
    } 
    
    // 详情页获取参数
    this.$route.params.id
  • 通过 $router.push 的 params 传参

    // 列表页传参
    goDetail(row) { this.$router.push({
            name: 'detail',
            params: {
                id: row.id
            }
        })
    } 
    
    // 详情页获取
    this.$route.params.id

    注:这种方式的传参,路径用 name,路径用 name,路径用 name , 用 path 会获取不到;如果在路由配置中没有添加 /:id 即 path: 'detail',url 中不会显示 id,在详情页还是可以拿到参数 id,但刷新后参数丢失。

  • 以上这两种方式,传递的参数 id 会在 url 后面显示,如图:

    image传递的参数会暴露在网址中。

    如果在路由中设置了params参数 /:id,但是在跳转的时候没有传递参数,会导致页面没有内容或跳转失败,可在后面加 ?代表这个参数是可选的,即 /:id?

方法二:通过 query 传参

// 路由配置
{ 
    path: '/detail', 
    name: 'detail', 
    component: Detail 
} 

// 列表页
goDetail(row) { this.$router.push({
        path: '/detail',
        query: {
            id: row.id
        }
    })
} 

// 详情页
this.$route.query.id

注:这种方式传递的参数会在地址栏的 url 后面显示 ?id=?,类似于 get 传参;query 必须配合 path 来传参

传递的参数是对象或数组

还有一种情况就是,如果通过 query 的方式传递对象或数组,在地址栏中会被强制转换成 [object Object],刷新后也获取不到对象值。

此时可以通过 JSON.stringify() 方法将要传递的参数转换为字符串传递,在详情页再通过 JSON.parse() 转换成对象。

let parObj = JSON.stringify(obj) 
this.$router.push({
    path: '/detail',
    query: { 
        'obj': parObj
    }
}) 

// 详情页
JSON.parse(this.$route.query.obj)

这个方法虽然可以传递对象,若数据少还好,数据多的话地址栏就很长了

注意:在所有的子组件中获取路由参数是 $route 不是 $router

以上 params 和 query 传参方式对比:

  • 通过 $router.push 的 params + name 传参,若路由中没有设置params参数,参数不会拼接在路由后面,但是页面刷新参数会丢失。
  • 通过 $router.push 中 path 携带参数或通过 query 传参,参数会拼接在地址后面,会暴露信息。

方法三:使用 props 配合组件路由解耦

// 路由配置
{ 
    path: '/detail/:id',
    name: 'detail', 
    component: Detail,
    props: true // 如果props设置为true,$route.params将被设置为组件属性
} 

// 列表页
goDetail(row) { this.$router.push({
        path: '/detail',
        query: {
            id: row.id
        }
    })
} 

// 详情页
export default {
    props: { // 将路由中传递的参数id解耦到组件的props属性上
 id: String
    },
    mounted: {
        console.log(this.id)
    }
}

详见:动态路由匹配    路由组件传参

此外,还可以通过把参数存在 sessionStorage 或 localStorage 中来解决页面刷新参数丢失的问题,具体结合实际项目即可。

查看原文

赞 0 收藏 0 评论 0

sugar_coffee 回答了问题 · 10月16日

解决elementUI的page-sizes设置完无效

layout="total, sizes, prev, pager, next, jumper"

少了sizes

关注 3 回答 2

sugar_coffee 回答了问题 · 10月16日

vue项目升级命令 vue upgrade 无效

你不是已经安装好了么。。。
vue upgrade是更新相关插件的,如果有可以升级的会显示出来。
没有么,那就是最新的咯

关注 2 回答 1

认证与成就

  • 获得 17 次点赞
  • 获得 2 枚徽章 获得 0 枚金徽章, 获得 0 枚银徽章, 获得 2 枚铜徽章

擅长技能
编辑

(゚∀゚ )
暂时没有

开源项目 & 著作
编辑

(゚∀゚ )
暂时没有

注册于 5月12日
个人主页被 514 人浏览