前端JS-Day25

forEach和some的区别:forEach用于遍历数组每一项,遇到return不会终止迭代。some遇到return true会终止迭代,效率更高,一般用于查询数组的唯一项。

map方法:参数和功能与forEach类似,不同点在于map会返回一个新数组且map执行速度更快!

trim方法:去除字符串两端的空格,返回一个新的字符串

 

对象方法:

Object.keys方法:参数为对象,用于遍历对象,console.log输出为对象的属性(无具体值)。

delete方法:删除对象属性。eg:delete obj.属性

Object.defineProperty方法:参数为:对象,属性名,特性(对象格式)用于修改对象属性。(vue的关键方法)

特性包括:value值,writeable是否可被重写,enumerable是否能被遍历(默认为false且只在使用Object.defineProperty方法时创建的属性才为false,原有属性不会受到影响),configurable为是否能被删除。

当我们需要在对象找方法的时候可以使用console.dir()进行打印。

console.log和console.dir区别:

  • console.log()可以取代alert()document.write(),在网页脚本中使用console.log()时,会在浏览器控制台打印出信息
  • console.dir()可以显示一个对象所有的属性和方法。

 

函数定义:

1.自定义函数:fuction fn(){}

2.函数表达式:let fn = fuction(){}

3.new Function方法: let fn = new Function('参数','函数体')

注意:所有函数都是Function的实例对象,故函数也属于对象,故函数也有原型,故也符合原型链。

函数调用:

<script>
        // 普通函数
        function fn1() {
            console.log('普通函数');
        } 
        fn1();

        // 对象方法
        let o = {
            fn2:function() {
                console.log('对象函数');
            }
        }
        o.fn2();
        
        // 构造函数
        function Fn3(){};
        new Fn3();
        
        // 绑定事件函数
        btn.onclick() = function() {};
        
        // 定时器函数
        setInterval(function(){}, interval);
            
        // 立即执行函数 自动调用
        (function(){})();
    </script>

 

函数内部的this指向:

1.普通函数:指向window

2.对象方法:指向该方法所属对象

3.构造函数:指向实例化对象,原型对象里的方法也指向实例对象

4.绑定事件函数:指向绑定的对象即函数调用者

5.定时器函数:指向window

6.立即执行函数:指向window

 

改变函数内部的this指向:

1.call方法:

参数:(this对象,传参....)

作用:①调用函数、②改变this指向、③实现继承

2.apply方法:

参数:(this对象,[参数])传参必须是数组形式(伪数组)!

作用:①调用函数、②改变this指向、③借助数学对象实现数组的新方法

apply实现数组的一些方法:

let arr = [1, 2, 3, 5];        
let maxV = Math.max.apply(Math, arr);
console.log(maxV);  // 输出最大值即5

 

3.bind方法:不会调用函数,仅进行一个绑定的过程!

参数:(this对象,参数...)

作用:①改变this指向、②返回一个新函数(原函数的拷贝,this已改变)

 

 

如果不希望调用函数但又希望改变该函数的this指向,就使用bind方法

例如:对一个按钮实现点击禁用但三秒后又要开启,但如果直接在setTimeout里用this,this指向的是window而不会改变按钮的属性,此时采用的是bind方法,故不会直接去调用定时器内部的函数,所以要在定时器的回调函数外部设置bind方法改变this的指向到调用者btn按钮,这样内部的this指向就变为了btn按钮,便可以设置属性。

<button>123213</button>
    <script>
        let btn = document.querySelector('button');
        btn.onclick = function() {
            this.disabled = true;
            setTimeout(function(){
                // 由于定时器函数内部this指向window故不能直接使用this解放按钮
                this.disabled = false;
            }.bind(this), 3000);
        }
    </script>

 

call、apply、bind总结:

相同:都可以改变函数内部的this的指向。

不同:1.call和apply会直接调用函数,bind不会。2.apply传参是伪数组形式,call和bind为正常传入。

运用场景:call经常做继承。apply与数组有关,实现数组的一些方法。bind实现不调用函数就改变this指向,例如修改定时器的this指向。

 

严格模式:具有限制性js的变体方式,即在限制性条件下执行js代码。

 

开启严格模式:'use strict'语句

1.为脚本开启严格模式:

 

2.为函数开启严格模式:

 

严格模式中的变化:

1.变量规定:

① 严禁使用未声明的变量。

② 严禁删除已经定义好的变量:delete X是非法的。

2.this指向:

① 正常模式下全局作用域中的this一般指向window,严格模式下全局作用域中this指向undefined。

② 在严格模式下,构造函数不加new就去调用,this指向undefined,给它赋值会报错。

③ 定时器在严格模式下,this仍然指向window。

④ 事件、对象的this仍然指向调用者。

3.函数变化:

① 严格模式下函数中不能有重复名的参数。

② 函数必须声明在顶层,ES6的块级作用域不允许在非函数的代码块中声明函数。即不能在for循环或者if语句内声明函数。

 

高阶函数:对其他函数进行操作的函数,它接受函数为参数或返回值为函数。

 <script>
        function fn(a, b) {
            a && a();
            b && b();
        };
        fn(function(){
            console.log(123);
        }, function(){
            console.log(456);
        })
</script>

 

闭包closure:一个函数对周围状态的引用捆绑在一起,内层函数中访问到其外层函数的作用域。

闭包 = 内层函数 + 外层函数的变量。

简单来说就是一个作用域可以访问另外一个函数内部的局部变量。

1.变量作用域:全局变量和局部变量。

① 函数内部可以使用全局变量。

② 函数外部不能使用局部变量。

③ 函数执行完毕,内部局部变量会销毁。

2.闭包作用:封闭数据,延伸了变量的作用范围,外部可以访问函数内部的变量。

function fn() {
            let num = 10;
            return function () {
                console.log(num);
            }
        }
        const f = fn();
        f();
        // 此时外部可以访问到内部的num值则fn为闭包

 闭包运用:实现数据私有

// 需求:输出函数被调用次数
        let i = 0;
        function fn1() {
            i++;
            console.log(i);
        }
        // 旧版实现,i为全局变量,一旦被修改则输出错误。

        function fn2() {
            let i = 0;
            return function() {
                i++;
                console.log(i);
            }
        }
        // 闭包方式实现,实现数据私有,不会被强制修改!

闭包可能引起内存泄漏!!

立即执行函数+闭包,解决异步问题。

 

递归函数:函数内部自己调用自己。

递归函数一定要设置退出条件。

利用递归实现遍历对象元素:

<script>
        var data = [{
            id: 1,
            name: '家电',
            goods: [{
                id: 11,
                gname: '电视'
            }, {
                id: 12,
                gname: '洗衣机'
            }]
        }, {
            id: 2,
            name: '服饰'
        }];
        // 利用forEach遍历每一个对象且forEach递归时会自动退出
        var o = {};
        function getId(json, id) {
            json.forEach(function (item) {
                if (item.id === id) {
                    o = item;
                } else if (item.goods && item.goods.length > 0) {
                    o = getId(item.goods, id);
                }
            });
            return o;
        }
        console.log(getId(data, 1));
        console.log(getId(data, 2));
        console.log(getId(data, 11));
        console.log(getId(data, 12));
    </script>

 

浅拷贝和深拷贝:

浅拷贝:只是拷贝一层,更深层次的对象只拷贝引用即拷贝的是地址。

!!浅拷贝修改值会影响原对象本身的值!!

浅拷贝语法糖:Object.assign(需要拷贝的对象,原对象);

 

深拷贝:拷贝多层,每一层的对象都会被拷贝。

function deepCopy(newobj, oldobj) {
            for (var k in oldobj) {
                // 判断简单数据类型还是复杂数据类型
                // 1.获取属性值 2.判断数据类型
                var item = oldobj[k];
                if (item instanceof Array) {
                    newobj[k] = [];
                    deepCopy(newobj[k], item);
                } else if (item instanceof Object) {
                    newobj[k] = {};
                    deepCopy(newobj[k], item);
                } else {    
                    newobj[k] = item;
                }
            }
        }

 

posted @ 2022-09-10 10:01  HM-7  阅读(31)  评论(0)    收藏  举报