JS入门到精通详解 对象详解与深浅拷贝(面试题)(15)

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6

对象详解

Object.defineProperty

  1. Object.defineProperty(obj, prop, descriptor) 方法会直接在一个对象上定义一个新属性或者修改一个对象的现有属性并返回此对象。

  • obj : 要定义属性的对象。

  • prop : 要定义或修改的属性的名称。

  • descriptor : 要定义或修改的属性描述符。

  1. 对象里目前存在的属性描述符有两种主要形式数据描述符存取描述符数据描述符是一个具有值的属性该值可以是可写的也可以是不可写的。存取描述符是由 getter 函数和 setter 函数所描述的属性。

  1. 数据描述符

  • configurable:表示能否通过delete删除属性从而重新定义属性能否修改属性的特性或者能否把属性修改为访问器属性默认值为false。

var obj = {
    name : "张三"
}
Object.defineProperty(obj,"name",{
    configurable : false
})
console.log(obj); //{name : "张三"}
delete obj.name;
console.log(obj); //{name : "张三"}
  • enumerable表示能否通过for in循环访问属性默认值为false

  • writable表示能否修改属性的值。默认值为false。

var obj = {
    name : "张三"
}
Object.defineProperty(obj,'age',{
    writable : false,
    value : 18
})
console.log(obj.age); //18
obj.age = 20;
console.log(obj.age); //18
  • value包含这个属性的数据值。默认值为undefined。

  1. 存取描述符

  • getgetter在读取属性时调用的函数默认值是undefined

  • setsetter在写入属性的时候调用的函数默认值是undefined

  • setter 不能和writable 、value 一起使用。不然报错。

var obj = {
    _year : 2022
}
Object.defineProperty(obj,'year',{
    get : function(){
        return this._year;
    },
    set : function(yyyy){
        if(yyyy > 2022){
            this._year = yyyy;
        }
    }
})
obj.year = 2023;
console.log(obj._year);
  1. 定义多个属性

var student = {};
var obj = {};
Object.defineProperties(student,{
    name: {
        writeble : false,
        value: "张三"
    },
    age : {
        writeble: true,
        value: 16
    },
    sex: {
        get(){
            return '男';
        },
        set(v){
            obj.sex = v;
        }
    }
})
obj.sex = '男';
console.log(student.name + ':' + student.age); //张三:16
console.log(obj.sex); //男
student.sex = '女';
console.log(student.sex); //男
console.log(obj.sex); //女

Proxy

  1. 概念

Proxy : ES6提供的数据代理表示由它来“代理”某些操作可以称为“代理器"
  1. 语法

new Proxy(代理原始对象,{配置项}) 返回的实例对象就是代理结果数据
  • new Proxy()表示生成一个Proxy实例

  • 代理原始对象 要被代理的对象可以是一个object或者function

  • 配置项也是一个对象对该代理对象的各种操作行为处理。

  • Proxy 可以理解成在目标对象之前架设一层“拦截”外界对该对象的访问都必须先通过这层拦截因此提供了一种机制可以对外界的访问进行过滤和改写

let obj = {name: '张三',age: 18};
//开始代理
let result = new Proxy(obj,{
    //配置get来进行代理设置
    get(target,property){
        //target: 就是你要代理的目标对象我们当前是obj
        //property: 就是该对象内的每一个属性自动遍历
        return target[property];
    },
    //配置set来进行修改
    set(target,property,val){
        //target: 就是你要代理的目标对象我们当前是obj
        //property: 就是该对象内的你要修改的那个属性
        //val: 就是你要修改的那个属性的值
        target[property] = val;
        console.log('你在修改' + property + '属性,你想修改为' + val);
        //注意简单代理需要返回 true
        return true;
    }
})
console.log('原始数据' + obj);
console.log('代理结果' + result);
console.log('代理结果 name : ' + result.name);

//尝试修改
result.name = '李四';
console.log('代理结果 name: ' + result .name);

//动态插入
result.sex = '男';
console.log('代理结果 sex:' + result.sex);

hasOwnProperty相当于===

in相当于==

hasOwnProperty 表示是否有自己的属性。这个方法会查找一个对象是否有某个属性但是不会去查找它的原型链。
let obj = {
    a : 1,
    fn : function(){},
    c : {
        d : 2
    }
}
console.log(obj.hasOwnProperty('a')); //true
console.log(obj.hasOwnProperty('fn')); //true
console.log(obj.hasOwnProperty('c')); //true
console.log(obj.c.hasOwnProperty('d')); //true
console.log(obj.hasOwnProperty('d')); //false

let str = new String();
console.log(str.hasOwnProperty('charAt')); //false
console.log(String.prototype.hasOwnProperty('charAt')); //true
判断自身属性是否存在
let obj = new Object(); //创建一个空对象
obj.name = '张三'; //添加一个name属性
//备份一份旧的name属性然后删除旧属性
function changeObj(){
    obj.newname = obj.name;
    delete obj.name;
}
console.log(obj.hasOwnProperty('name')); //true
changeObj();
console.log(obj.hasOwnProperty('name')); //false
判断自身属性与继承属性
function foo() {
    this.name = 'foo'
    this.sayHi = function () {
        console.log('Say Hi')
    }
}

foo.prototype.sayGoodBy = function () {
    console.log('Say Good By')
}

let myPro = new foo()

console.log(myPro.name) // foo
console.log(myPro.hasOwnProperty('name')) // true
console.log(myPro.hasOwnProperty('toString')) // false
console.log(myPro.hasOwnProperty('hasOwnProperty')) // false
console.log(myPro.hasOwnProperty('sayHi')) // true
console.log(myPro.hasOwnProperty('sayGoodBy')) // false
console.log('sayGoodBy' in myPro) // true
遍历一个对象的所有自身属性:使用hasOwnProperty()方法来忽略继承属性。
var buz = {
    a: 1
};

for (var name in buz) {
    if (buz.hasOwnProperty(name)) {
        alert(name + ':' + buz[name]);
    }
    else {
        alert(name); 
    }
}

深浅拷贝面试题

针对引用类型而言浅拷贝指的是复制对象的引用即直接给引用类型赋值如果拷贝后的对象发生变化原对象也会发生变化。而深拷贝是真正地对对象进行拷贝修改拷贝后的新对象并不会对原对象产生任何影响。
在JS中数据类型分为基本类型和引用类型 基本类型: number booleanstringsymbolundefinednull
引用类型object 以及一些标准内置对象 Array、RegExp、String、Map、Set..

基本类型数据拷贝值拷贝

基本类型数据都是值类型存储在栈内存中每次赋值都是一次复制的过程
var a = 12;
var b = a;
console.log(a,b); //12  12
a = 13;
console.log(a,b); //13  12

引用类型数据拷贝

只拷贝对象的一层数据再深处层次的引用类型value将只会拷贝引用

浅拷贝

//浅拷贝的特点

//1. 拷贝的是对象的引用地址

//2. 当我修改一个对象中的属性时两个对象中的属性会同时改变。

let obj = {
    a : 1,
    b : {
        c : 2,
        d : {
            f : 3
        }
    }
}
let newObj = {... obj};
console.log(newObj);
obj.b.c = 10;
console.log(newObj);
function cloneObj(obj){
    let clone = {};
    for(let key in obj){
        clone[key] = obj[key];
    }
    return clone;
}
let a = {
    x : {
        y : 1
    }
}
let b = cloneObj(a);
console.log(a,b);

深拷贝

深拷贝就不会像浅拷贝那样只拷贝一层而是有多少层我就拷贝多少层要真正的做到全部内容都放在自己新开辟的内存里。可以利用递归思想实现深拷贝。
function cloneObj(obj) {
    let clone = {};
    for (let i in obj) {
        // 如果为对象则递归更进一层去拷贝
        if (typeof obj[i] == "object" && obj[i] != null) {
            clone[i] = cloneObj(obj[i]);
        } else {
            clone[i] = obj[i];
        }
    }
    return clone;
}
阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6