centos7安装 junit bluetooth stream android项目实例 jquery的点击事件 oracle修改字段默认值 git下载项目 mysql查询结果拼接 plsql卸载 python类和对象 python中set的用法 python循环10次 python怎么使用 python函数返回 java时间 java时间戳转换成时间 学习java基础 java数组转集合 java怎么输出数组 java定义字符串 linux密码忘记 linuxshell编程 ntscan 服务器操作系统下载 街头篮球辅助 flash相册制作 战地2单机地图 销售单软件 ezcad2 图解深度学习 战地联盟辅助 无限视距 狮子狗皮肤 c语言编程实例 暴力猴插件 ps调整边缘抠头发丝 天正建筑2007 python延时函数 文字图片制作
当前位置: 首页 > 学习教程  > 编程语言

深拷贝 与 浅拷贝 原型 类型校验

2021/1/13 19:41:53 文章标签: 测试文章如有侵权请发送至邮箱809451989@qq.com投诉后文章立即删除

前提: 深拷贝和浅拷贝是只针对Object和Array这样的引用数据类型的。 1. 堆栈内存 具体看另一篇博客数据类型、堆栈存储 2. 浅拷贝与深拷贝 深拷贝和浅拷贝的示意图大致如下: 浅拷贝只复制指向某个对象的指针,而不复制对象本身&#xff0c…

前提:

深拷贝和浅拷贝是只针对Object和Array这样的引用数据类型的。

1. 堆栈内存

具体看另一篇博客数据类型、堆栈存储

2. 浅拷贝与深拷贝

深拷贝和浅拷贝的示意图大致如下:
在这里插入图片描述

浅拷贝只复制指向某个对象的指针,而不复制对象本身,新旧对象还是共享同一块内存。但深拷贝会另外创造一个一模一样的对象,新对象跟原对象不共享内存,修改新对象不会改到原对象。

赋值和浅拷贝的区别
赋值:

把一个对象赋值给一个新的变量时,赋的其实是该对象的在栈中的地址,而不是堆中的数据。也就是两个对象指向的是同一个存储空间,无论哪个对象发生改变,其实都是改变的存储空间的内容,因此,两个对象是联动的。

浅拷贝:

浅拷贝是按位拷贝对象,它会创建一个新对象,这个对象有着原始对象属性值的一份精确拷贝。如果属性是基本类型,拷贝的就是基本类型的值;如果属性是内存地址(引用类型),拷贝的就是内存地址 ,因此如果其中一个对象改变了这个地址,就会影响到另一个对象。即默认拷贝构造函数只是对对象进行浅拷贝复制(逐个成员依次拷贝),即只复制对象空间而不复制资源。

手写深拷贝(递归):
/**
 * 深拷贝
 */

const obj1 = {
    age: 20,
    name: 'xxx',
    address: {
        city: 'beijing'
    },
    arr: ['a', 'b', 'c']
}

const obj2 = deepClone(obj1)
obj2.address.city = 'shanghai'
obj2.arr[0] = 'a1'
console.log(obj1.address.city)
console.log(obj1.arr[0])

/**
 * 深拷贝
 * @param {Object} obj 要拷贝的对象
 */
function deepClone(obj = {}) {
    if (typeof obj !== 'object' || obj == null) {
        // obj 是 null ,或者不是对象和数组,直接返回
        return obj
    }

    // 初始化返回结果
    let result
    if (obj instanceof Array) {
        result = []
    } else {
        result = {}
    }

    for (let key in obj) {
        // 保证 key 不是原型的属性
        if (obj.hasOwnProperty(key)) {
            // 递归调用!!!
            result[key] = deepClone(obj[key])
        }
    }

    // 返回结果
    return result
}

javascript原型与原型链

1. prototype

每个函数都有一个prototype属性,被称为显示原型

2._ proto _

每个实例对象都会有_ proto 属性,其被称为隐式原型
每一个实例对象的隐式原型
proto _属性指向自身构造函数的显式原型prototype

3. constructor

每个prototype原型都有一个constructor属性,指向它关联的构造函数。

4. 原型链

获取对象属性时,如果对象本身没有这个属性,那就会去他的原型__proto__上去找,如果还查不到,就去找原型的原型,一直找到最顶层(Object.prototype)为止。Object.prototype对象也有__proto__属性值为null。

这里需要注意的是Object是属于原型链的顶层,所有构造函数的的prototype都指向 Object.prototype

在这里插入图片描述


function Fun(){

  }
//    我创造了一个函数Fn
//   这个函数由Function生成(Function作为构造函数)
     var fn=new Fun()
//   我创建了一个函数fn
//   这个函数由构造函数Fun生成
     console.log(fn.__proto__===Fun.prototype)    //true
//   fn的__proto__指向其构造函数Fun的prototype
     console.log(Fun.__proto__===Function.prototype)        //true
//   Fun的__proto__指向其构造函数Function的prototype
     console.log(Function.__proto__===Function.prototype)    //true
//   Function的__proto__指向其构造函数Function的prototype
//   构造函数自身是一个函数,他是被自身构造的
     console.log(Function.prototype.__proto__===Object.prototype)    //true
//   Function.prototype的__proto__指向其构造函数Object的prototype
//   Function.prototype是一个对象,同样是一个方法,方法是函数,所以它必须有自己的构造函数也就是Object
     console.log(Fun.prototype.__proto__===Object.prototype)         //true
//   与上条相同
//   此处可以知道一点,所有构造函数的的prototype方法的__都指向__Object.prototype(除了....Object.prototype自身)
     console.log(Object.__proto__===Function.prototype)        //true
//   Object作为一个构造函数(是一个函数对象!!函数对象!!),所以他的__proto__指向Function.prototype
     console.log(Object.prototype.__proto__===null)        //true
//   Object.prototype作为一切的源头,他的__proto__是null

//  下面是一个新的,额外的例子

    var obj={}
//  创建了一个obj
    console.log(obj.__proto__===Object.prototype)        //true
//   obj作为一个直接以字面量创建的对象,所以obj__proto__直接指向了Object.prototype,而不需要经过Function了!!

//    下面是根据原型链延伸的内容
/*还有一个上文并未提到的constructor,  constructor在原型链中,是作为对象prototype的一个属性存在的,它指向构造函数
(由于主要讲原型链,这个就没在意、);*/

 console.log(obj.__proto__.__proto__===null)        //true
 console.log(obj.__proto__.constructor===Object)        //true
 console.log(obj.__proto__.constructor.__proto__===Function.prototype)        //true
 console.log(obj.__proto__.constructor.__proto__.__proto__===Object.prototype)    //true
 console.log(obj.__proto__.constructor.__proto__.__proto__.__proto__===null)        //true
 console.log(obj.__proto__.constructor.__proto__.__proto__.constructor.__proto__===Function.prototype)    //true

//            以上,有兴趣的可以一一验证  F12搞起.

js数据类型判断

四种方法

typeof、instanceof、constructor、Object.prototype.toString.call()、jquery.type()

1 .typeof

console.log(
    typeof 100, //"number"
    typeof 'abc', //"string"
    typeof false, //"boolean"
    typeof undefined, //"undefined"
    typeof null, //"object"
    typeof [1,2,3], //"object"
    typeof {a:1,b:2,c:3}, //"object"
    typeof function(){console.log('aaa');}, //"function"
    typeof new Date(), //"object"
    typeof /^[a-zA-Z]{5,20}$/, //"object"
    typeof new Error() //"object"
    typeof new Number(100), //'object'
    typeof new String('abc'),// 'string'
    typeof new Boolean(true),//'boolean'
);

基本数据类型中:Number,String,Boolean,undefined 以及引用数据类型中Function ,可以使用typeof检测数据类型,分别返回对应的数据类型小写字符。
另:用typeof检测构造函数创建的Number,String,Boolean都返回object
基本数据类型中:null 。引用数据类型中的:Array,Object,Date,RegExp。不可以用typeof检测。都会返回小写的object

2 . instanceof

除了使用typeof来判断,还可以使用instanceof。instanceof运算符需要指定一个构造函数,或者说指定一个特定的类型,它用来判断这个构造函数的原型是否在给定对象的原型链上。


console.log(
    100 instanceof Number, //false
    'dsfsf' instanceof String, //false
    false instanceof Boolean, //false
    undefined instanceof Object, //false
    null instanceof Object, //false
    [1,2,3] instanceof Array, //true
    {a:1,b:2,c:3} instanceof Object, //true
    function(){console.log('aaa');} instanceof Function, //true
    new Date() instanceof Date, //true
    /^[a-zA-Z]{5,20}$/ instanceof RegExp, //true
    new Error() instanceof Error //true
)

基本数据类型中:Number,String,Boolean。字面量值不可以用instanceof检测,但是构造函数创建的值可以,如下:


var num = new Number(123);
var str = new String('dsfsf');
var boolean = new Boolean(false);

还需要注意null和undefined都返回了false,这是因为它们的类型就是自己本身,并不是Object创建出来它们,所以返回了false。

3 .constructor

constructor是prototype对象上的属性,指向构造函数。根据实例对象寻找属性的顺序,若实例对象上没有实例属性或方法时,就去原型链上寻找,因此,实例对象也是能使用constructor属性的。

如果输出一个类型的实例的constructor,就如下所示:


console.log(new Number(123).constructor)
//ƒ Number() { [native code] }

可以看到它指向了Number的构造函数,因此,可以使用num.constructor==Number来判断一个变量是不是Number类型的。


var num  = 123;
var str  = 'abcdef';
var bool = true;
var arr  = [1, 2, 3, 4];
var json = {name:'wenzi', age:25};
var func = function(){ console.log('this is function'); }
var und  = undefined;
var nul  = null;
var date = new Date();
var reg  = /^[a-zA-Z]{5,20}$/;
var error= new Error();

function Person(){
  
}
var tom = new Person();

// undefined和null没有constructor属性
console.log(
    tom.constructor==Person,
    num.constructor==Number,
    str.constructor==String,
    bool.constructor==Boolean,
    arr.constructor==Array,
    json.constructor==Object,
    func.constructor==Function,
    date.constructor==Date,
    reg.constructor==RegExp,
    error.constructor==Error
);
//所有结果均为true

除了undefined和null之外,其他类型都可以通过constructor属性来判断类型。

4 . 使用Object.prototype.toString.call()检测对象类型

可以通过toString() 来获取每个对象的类型。为了每个对象都能通过 Object.prototype.toString() 来检测,需要以 Function.prototype.call() 或者 Function.prototype.apply() 的形式来调用,传递要检查的对象作为第一个参数,称为thisArg。

var toString = Object.prototype.toString;

toString.call(123); //"[object Number]"
toString.call('abcdef'); //"[object String]"
toString.call(true); //"[object Boolean]"
toString.call([1, 2, 3, 4]); //"[object Array]"
toString.call({name:'wenzi', age:25}); //"[object Object]"
toString.call(function(){ console.log('this is function'); }); //"[object Function]"
toString.call(undefined); //"[object Undefined]"
toString.call(null); //"[object Null]"
toString.call(new Date()); //"[object Date]"
toString.call(/^[a-zA-Z]{5,20}$/); //"[object RegExp]"
toString.call(new Error()); //"[object Error]"

这样可以看到使用Object.prototype.toString.call()的方式来判断一个变量的类型是最准确的方法。

5 .无敌万能的方法:jquery.type()

如果对象是undefined或null,则返回相应的“undefined”或“null”

jQuery.type( undefined ) === "undefined"
jQuery.type() === "undefined"
jQuery.type( window.notDefined ) === "undefined"
jQuery.type( null ) === "null"
/*如果对象有一个内部的[[Class]]和一个浏览器的内置对象的 [[Class]] 相同,我们返回相应的 [[Class]] 名字。
 (有关此技术的更多细节。 )*/
jQuery.type( true ) === "boolean"
jQuery.type( 3 ) === "number"
jQuery.type( "test" ) === "string"
jQuery.type( function(){} ) === "function"
jQuery.type( [] ) === "array"
jQuery.type( new Date() ) === "date"
jQuery.type( new Error() ) === "error" // as of jQuery 1.9
jQuery.type( /test/ ) === "regexp"
其他一切都将返回它的类型“object”

6 . 自己也可以封装一个获取变量准确类型的函数

function gettype(obj) {
var type = typeof obj;

if (type !== ‘object’) {
return type;
}
//如果不是object类型的数据,直接用typeof就能判断出来

//如果是object类型数据,准确判断类型必须使用Object.prototype.toString.call(obj)的方式才能判断
return Object.prototype.toString.call(obj).replace(/^[object (\S+)]$/, ‘$1’);
}


本文链接: http://www.dtmao.cc/news_show_600161.shtml

附件下载

相关教程

    暂无相关的数据...

共有条评论 网友评论

验证码: 看不清楚?