克隆+数组+try...catch--大一下第八周笔记

克隆

arguments表示实参列表,是一个数组

浅层克隆

实现一个demo,不过因为是原始值,所以只是值拷贝

        var obj = {
    
    
            name : 'abc',
            age : 123,
            sex : 'female'
        }
        var obj1 = {
    
    }

        function clone(origin, target){
    
    
            var target = target || {
    
    };//防止没有target这种情况
            for ( var prop in origin){
    
    
                target[prop] = origin[prop];
            }
            return target;
        }

        clone(obj, obj1);

如果在obj中加入一个数组,那么在obj中就有了引用值,当这样克隆的时候,obj和obj1中的数组那个属性都指向一个地址
如何才能让克隆过来的引用值也拥有不同于之前的地址呢?就是让所有值都是相对独立的
思路:判断数据是引用值还是原始值,如果是原始值,就直接拷贝,如果是数组或对象这样的引用值,就创建一个对象用来放接下来的数据
浅拷贝es6中有一个语法糖,就是Object.assign(target, origin);

深层克隆

步骤:
最先是遍历全部对象 利用for in
1.判断是不是原始值(原始值直接拷贝)–利用typeof() --数组或者对象都会返回object
2.判断是数组还是对象 --instanceof、toString、constructor,建议使用toString
3.建立相应的数组或对象
4.递归重复上面的行为

代码如下

        var obj = {
    
    
            name : 'abc',
            age : 123,
            card : ['visa', 'master'],
            wife : {
    
    
                name : 'bcd',
                son : {
    
    
                    name : 'aaa'
                }
            }
        }

        var obj1 = {
    
    };

        function deepClone(origin, target) {
    
    

            var target = target || {
    
    },
                toStr = Object.prototype.toString,
                arrStr = '[array Object]';

            for (var prop in origin){
    
    
                if (origin.hasOwnProperty(prop)) {
    
    
                    // 为了避免原型链上面的属性被copy
                    if(origin[prop] !== 'NULL' && typeof(origin[prop]) == 'object') {
    
    

                        // if (toStr.call(origin[prop]) == arrStr) {
    
    
                        //     target[prop] = [];
                        // }else{
    
    
                        //     target[prop] = {};
                        // }
                        // 用三目运算符来简化一下这个if else语句

                        target[prop] = toStr.call(origin[prop]) == arrStr ? [] : {
    
    };
                        deepClone(origin[prop], target[prop]);
                    }else{
    
    
                        target[prop] = origin[prop];
                    }
                }
            }
            return target;
        }

这样就基本实现了所想要的功能,让两者相对独立,如图
在这里插入图片描述

三目运算符:条件判断 ? 表达式1 : 表达式2;
在条件成立的情况下,执行表达式1,否则执行表达式2

数组

数组实际上是一种特殊的对象

定义数组

  1. 定义数组自面量(推荐)
    var arr = [];

  2. 构造方法定义数组
    var arr = new Array();

两种方法的区别:
分别用这两种方法,传入10

    var arr = new Array(10);
    var arr1 = [10];

在这里插入图片描述

构造方法里面传入一个数字,表达这个数组的长度,所以在构造方法里面,要注意不能传入小数

数组的读写

如果数组直接越界进行写入,前面未定义的会直接表示undefined,然后在想写入的那个地方写入数据,如果溢出读,会返回undefined,两者均不会报错

数组的常用方法

如果在函数里面传入负数,他会执行如下步骤

    splice = function (pos){
    
    
        pos += pos > 0 ? 0 : this.length; 
    }

改变原数组

  1. push()
    在数组的最后添加数据(可以一次添加多个),然后返回数组的长度
    自己实现一下push的功能,代码如下,在调用函数的时候,传进去的实参储存在arguments里面,this.length是在每一次循环的时候自动增长的
    var arr = [1,2,3];
    Array.prototype.push = function () {
    
    
        for(var i = 0; i < arguments.length; i++){
    
    
            this[this.length] = arguments[i];
            console.log(this.length);
        }
        return this.length;
    }
  1. pop()
    从数组的最后一位剪切,传入数据没用

  2. shift()
    从数组的最前面一位剪切,和pop差不多

  3. unshift()
    从数组的最前面开始加入数据,和push差不多

  4. reverse()
    把数组逆置,返回原数组

  5. splice(从第几位开始, 截取多少的长度, 在切口处添加新的数据)
    返回截取的部分

  6. sort()
    将数组里面的数字按升序排列,如果想要降序,在sort函数后面加上reverse函数(排序按照ASCII码来排序的,所以只能排字符

    // 规则:
    // 1. 必须写两个形参
    // 2. 看返回值 1) 当返回值为负数时,那么前面的数放在前面
    //             2) 当返回值为正数时,后面的数在前
    //             3) 为0时,不动
    //类似冒泡排序的方法比较 
    var arr = [1, 2, 3, 9, 6, 4];
    arr.sort(function (a, b) {
    
    

        // if (a > b) {
    
    
        //     return 1;
        // }else{
    
    
        //     return -1;
        // }

        return b - a; 
        // 两种结果一样
 
    });

不能改变原数组

  1. concat()
    将两个数组拼接起来,成为一个全新的数组
    arr.concat(arr1);表示把arr1拼接到arr后面,可以进行多个数组的拼接

  2. toString()
    就是把数组转变成字符串展示出来

  3. slice(从该位开始截取,截取到该位)
    不会改变原数组,如果是一个参数,那就是从第几位开始,一直截取到最后一位
    不写就是全部截取

  4. join()
    括号里面传字符串,哪怕是传一个空串,返回一个以传入字符串为每个数之间的间隔的字符串,如果不传,就会默认以逗号相连,例如
    在这里插入图片描述

  5. split()
    表示按照括号内的拆分,而且直接就让括号里面的内容消失,如下
    在这里插入图片描述
    在这里插入图片描述

类数组

和数组相似,但其实不是数组

类数组的要求:属性要为索引(数字)属性,必须要有length属性,最好加上push

    var obj = {
    
    
        "0" : 'a',
        "1" : 'b',
        "2" : 'c',
        "length" : 3,
        "push" : Array.prototype.push
    }

展示一个题

    var obj = {
    
    
        "2" : 'a',
        "3" : 'b',
        "length" : 2,
        "push" : Array.prototype.push
    }

    obj.push('c');
    obj.push('d');

输出结果如图所示
在这里插入图片描述

可知length属性最为重要

分装type实现完全的typeof作用

        function type(target){
    
    
            var template = {
    
    
                '[object Array]' : 'array',
                "[object Object]" : "object",
                "[object Number]" : "number - object",
                "[object Boolean]" : "boolean - object",
                "[object String]" : "string - object"
            }
            if (target == null){
    
    
                return 'null';
            }
            if(typeof(target) == 'object'){
    
    
                // 数组,对象,包装类
                var str = Object.prototype.toString.call(target);
                return template[str];
            }else{
    
    
                return typeof(target);
            }
        }

实现数组去重

// 方法一:
        var arr = [1,1,1,1,3,3,3,5,5,5];
        var arr1 = [];
        function change(arr){
    
    
            for(var i =  0; i < arr.length; i ++){
    
    
                if (arr1.length == 0){
    
    
                    arr1.push(arr[i]);
                }else{
    
    
                    var count = 0;
                    for( var j = 0 ; j < arr1.length ; j ++){
    
    
                        if (arr1[j] == arr[i] ){
    
    
                            count++;
                        }
                    }
                    if(count == 0){
    
    
                        arr1.push(arr[i]);
                    }
                }
            }
            return arr1;
        }
// 方法二:hash方法
        Array.prototype.unique = function(){
    
    
            var temp = {
    
    },
                arr = [],
                len = this.length;//将this.length取出来是为了减少在后续多处使用this.length时的运算量
            for (var i = 0; i < len; i ++){
    
    
                if(!temp[this[i]]){
    
    
                    temp[this[i]] = 'abc';//这个值可以是其他,但是需要是非0的,因为在最前面判断的时候,需要一个非0的值来判断
                    arr.push(this[i]);
                }
            }
            return arr;
        }

hash利用了对象里面属性名不能重复的原理,当属性名不存在的时候,返回undefined

前面知识复习

  1. 一旦经历var的操作,所得出的属性叫做不可配置属性,不可配置属性delete不掉

  2. undefined和null不能和数进行比较

  3. 形参的变量相当于var一个this

  4. Object.creat(prototype, definedProperty),前一个变量是原型,后一个变量是特性,特性具体是些啥,还有待探究

  5. func();相当于func.call();执行,在没有传入任何参数的时候,就是预编译的this指向

try…catch

用来找错误,将不确定是否正确的代码放入try中,如果出现错误,就会停止try中的代码的执行,然后继续执行外面的代码,这个过程不会报错,只会跳过try里面错误代码之后代码的执行,如果存在错误,那么catch就会将错误捕捉,catch里面传入的数据就相当于一个形参,她存在两个属性值,error.message和error.name,可以通过这两个属性找出代码的bug要注意的是,try…catch每次只能找到一处bug,因为在try执行的时候,遇到bug就终止执行try后面的部分了。
举个例子

        try{
    
    
            console.log('a');
            console.log(b);
        }catch(e){
    
    
            console.log(e.name + ' ' + e.message);
        }
        console.log('try外面')

结果如图
在这里插入图片描述

对一些错误信息的了解

  1. EvalError:eval()的定义和使用不一致

  2. RangeError:数值越界

  3. ReferenceError:非法或不能识别引用数值

  4. SyntaxError:发生语法解析错误

  5. TypeError:操作数类型错误

  6. URIError:URI处理函数使用不当

ES5严格模式

现在普遍的使用是基于es3.0,配合es5.0的新增方法共同使用,当产生冲突的时候,会使用es3.0版本的

当启用es5.0严格模式,那么此时产生冲突的部分会遵循es5.0的使用

如何启用呢?
在逻辑块的最前面写上一行的代码,‘use strict’;一定得是字符串格式,这样就会启用es5.0严格模式
可以是这个script标签的逻辑最前面,也可以是在一个函数的逻辑最前面,实现局部启用es5.0严格模式
也就是说,这个启用,可以是全局的,也可以是局部的

es5严格模式一些要求

  1. 禁用with
    with会改变作用域链,with里面填的对象会充当内部执行最近的作用域
    因为更改作用域链会浪费效率,是一个大工程,所以在es5严格模式里面就把with给限制了
        var obj = {
    
    
            name : 'bcd'
            }
        function test() {
    
    
            var name = 'abc';
            with(obj){
    
    
                console.log(name);
            }
        }

在这里插入图片描述

  1. 禁用arguments.callee,用于在立即执行函数里面执行递归

  2. 禁用func.caller,打印函数执行时所处的环境

  3. 赋值变量之前,必须进行声明

  4. 局部的this必须被赋值(赋值给什么就是什么)

  5. 拒绝重复属性和参数

猜你喜欢

转载自blog.csdn.net/weixin_50948265/article/details/116137593