JS高阶篇 03-改变this指向,继承,内置对象Array的操作方法

本文详细解释了JavaScript中`this`关键字在不同场景下的行为,介绍了call(),apply(),bind()方法如何改变`this`指向,并讨论了它们的应用场景,包括数据类型检测、定时器传参、构造函数和原型继承以及数组操作方法等。
摘要由CSDN通过智能技术生成

1.回忆

        1、在普通函数中this指向window

        2、在自执行函数this指向window

        3、在定时器this指向window

        4、在构建函数this执行实例化对象

        5、在对象方法中this指向该方法所属的对象

        6、在绑定事件中this指向绑定该事件的对象

        7、在构建函数原型对象上this指向实例化对象

2.改变this指向 

2.1 call()方法

语法:call(要指向的对象,参数,参数。。。。。。。。。)、

  var obj={
            name:'张三',
            age:34
        }
        function  max(x,y){
            console.log(this);
            console.log(x+y);
            console.log(this.age-x-y);
        }

 此时max()方法中的this指向为window对象

  max.call(obj,10,20)

就改变this的指向,此时this的指向就是obj

1、call会立即调用函数

2、参数传递的方式是以逗号隔开的

3、可以改变this的指向

2.1.1应用场景

检测数据类型 

通过 Object.prototype.toString.call(要检测的数据)(最精准的检测方式

Object.prototype.toString()判断数据类型

 console.log(Object.prototype.toString());       //[object Object]
 console.log(Object.prototype.toString.call(123));   //[object Number]

  console.log(Object.prototype.toString.call(new Date));  //[object Date]
 console.log(Object.prototype.toString.call(new RegExp));//[object RegExp]

 function fun() {

        }
    console.log(Object.prototype.toString.call(fun));   //[object Function]

2.2 apply()方法

语法:语法:call(要指向的对象,数组)、

  var obj={
            name:'张三',
            age:12
        }

        function sum(x,y){
            console.log(this);
            console.log(this.age+a+b);

        }
        sum.apply(obj,[20,20]);

1、apply 会立即调用函数

2、传入的参数是以数组形式

3、改变this指向

2.2.1应用场景

求最大值.....


        // 求最大值
        // Math.max
        var rel=Math.max(1,2,3,4,5,6,7);
        console.log(rel);   //7


        var arr=[342,464,46,424,646,535];
        //  先看apply(Math,arr);让this指向Math,然后Math.max求出最大值;
        var rel1 =Math.max.apply(Math,arr);
        console.log(rel1);

2.3 bind()方法

语法:var rel=obj.bind(要指向的对象,参数,参数。。。。。。。。。)

rel()   或call(要指向的对象,参数,参数。。。。。。。。。)()      需要调用  

 var obj={
            name:'李四',
            age:42
        }

        function sum(a,b){
            console.log(this);
            console.log(this.age+a+b)
        }
        // 在这一行bind只是把sum函数内部的this指向改变并没有调用函数,应该先改变this指向在调用该函数
        //并没有调用该函数

        var rel =sum.bind(obj,200,200);
        console.log(rel);           // ƒ sum(a,b){
                                    //     console.log(this);
                                    //     console.log(this.age+a+b)
                                    // } 

                                    // 只是指向了并没有调用该sum对象    


                                    // 先让this指向该对象在调用该函数
            var rel1 = sum.bind(obj,200,200)(); 
            console.log(rel1);  //{name: '李四', age: 42}   442

1、bind 不会立即调用 需要手动调用

2、传入的参数是以逗号隔开的

3、改变this指向

2.3.1 应用场景 

延迟应用定时器

<body>
    <button>5秒之后再次点击</button>
    <button>5秒之后再次点击</button>
    <button>5秒之后再次点击</button>
    <button>5秒之后再次点击</button>
    <button>5秒之后再次点击</button>

    <script>
        var btn = document.querySelectorAll("button");
        // var timerId = null;
        for (var i = 0; i < btn.length; i++) {

            btn[i].onclick = function () {

                this.disabled = true;
                var num = 5;

                var timerId = setInterval(function () {
                    num--;
                    if (num <= 0) {
                        this.disabled = false;
                        this.innerText = "5秒之后再次点击";
                        clearInterval(timerId);
                    } else {
                        this.innerText = num + "秒之后再次点击";
                    }

                }.bind(this), 1000);
            }
        }
    </script>

 

2.4 call / apply / bind 有啥区别

  • 共同点 : 都可以改变this指向
  • 不同点:
    • call 和 apply会立即调用函数.bind不会立即调用函数, 需要手动调用.
    • call及bind 和 apply传递的参数不一样,call及bind传递参数使用逗号隔开,apply使用数组传递.
  • 应用场景
    1. call 经常做继承.
    2. apply 经常跟数组有关系.  比如借助于数学对象实现数组最大值最小值
    3. bind  不调用函数,但是还想改变this指向. 比如改变定时器内部的this指向.

3.检测数据类型

1、typeof (检测基本数据类型)

 console.log(typeof num);        //number

2、instanceof    用于检测复杂数据类型

console.log(new Date instanceof Object);       //true
console.log(num instanceof Object);             //false
console.log(fun instanceof Function);           //true

3.constructor: 检测当前实例的构造函数

console.log(obj.constructor == Object);//true
console.log(date.constructor == Date);//true

  4、Object.prototype.toString.call()最精准的检测方式

console.log(Object.prototype.toString.call(123));   //[object Number]
console.log(Object.prototype.toString.call(new Date));  //[object Date]

4.定时器传参

    var j =10;
        setTimeout('fun(j)',3000);      //3s输出 30

        function fun(i){
            console.log(i+20);
        }

加引号会让定时器会在2s后运行,先运行定时器在运行函数

不加会直接调用函数,函数在定时器前面,会直接打印函数内容

作用: 

解决定时器不能传参的问题

在外部封装函数 写在定时器方法里面进行调用

 注意:要用引号将函数包括

 5.继承

5.1 构造函数继承

子构建函数继承父构建函数的属性

 使用call方式实现子继承父的属性

 // 父结构函数
        function Fun(name,age,gender){
            this.name=name;
            this.age=age;
            this.gender=gender;
            console.log(1);

        }
        var fun = new Fun("熊大",20,'动物');
        console.log(fun);  
        
        
        // 子构建函数
        function Son(name,age,gender){
            // this指向Fun参数
            console.log(2);
            console.log(this);

             //3.使用call方式实现子继承父的属性
            //  并没有改变this的指向,只是继承了父元素的属性
           console.log( Fun.call(this,name,age,gender));
            console.log(this);
        }
        var son = new Son('熊二',18,'动物');

5.2 原型对象继承方法

也是通过call来继承

 // 父结构函数
        function Fun (name,age,gender){
            this.name=name;
            this.age=age;
            this.gender=gender;
        }

        Fun.prototype.x=function(){
            console.log('翠花');

        }
        var rel = new Fun('熊大',20,'动物');
        console.log(rel);

        // 子构建函数
        function Son (name,age,gender){
            // 让子构建函数继承父构建函数的属性
            // 不会改变this的指向
            Fun.call(this,name,age,gender);
        }

        // 原型继承 如果直接使用原型对象赋值的方式 继承 那么两个对象会指向同一个数据
        // 修改其中一个 另外一个也会被修改 ;
        // 
        // Son.prototype=Fun.prototype;


        // 应该
        Son.prototype=new Fun();    //constructor:ƒ Fun(name,age,gender)
        // 此时constructor 指向父元素
        // 所以这里必须要多一步 让son 的constructor指回本身
        Son.prototype.constructor=Son;  //constructor:ƒ Son(name,age,gender)


        // 在子元素的原型上添加修改方法不会改变父元素的方法
        Son.prototype.gtq=function(){
            console.log('光头强');
        }

        
        var son = new Son('熊二',18,'动物');
        console.log(son);

5.3 Object.create实现类式继承

内一个方法Object.create(proto, [propertiesObject])

  function Fun (a){
            this.a=a;
        }
        var rel = new Fun('170cm');

        console.log(rel);

        //         渴热奥特
        // Object.create()

        // 第一个参数是以谁为原型创建对象
        // 第二个参数 传入一个对象用来设置 新对象的值和属性特征;

        var rel1 =Object.create(rel,{
            name:{
                // 也可以不加下列该属性,下列属性起到权限的作用1
                configurable:true,
                enumerable:true,
                writable:true,
                value:"玛玛哈哈"
            },age:{
                configurable:true,
                enumerable:true,
                writable:true,
                value:20
            }
        })
        console.log(rel1);
        // 继承到原型对象的上
        console.log(rel1.a);        //170cm

6.数组操作方法

不会对伪数组进行操作

都不会改变原数组

        6.1 数组方法forEach遍历数组

语法:

forEach遍历数组 
arr.forEach(function(value, index, array) {
       //参数一是:数组元素
       //参数二是:数组元素的索引
       //参数三是:当前的数组
 })
  //相当于数组遍历的 for循环 没有返回值
var arr = [1, 2, 3, 5, 6, 7, 89];
        // 遍历数组
        var rel = arr.forEach(function (value, index, arr) {
            // value当前元素
            // index元素的索引
            // arr当前数组
            console.log(value);
        })

每次运行都会对数组的每一个值进行遍历

6.2 数组方法map遍历数组

map() 方法返回一个新数组,数组中的元素为原始数组元素调用函数处理后的值。

map() 方法按照原始数组元素顺序依次处理元素。

注意: map() 不会对空数组进行检测, map() 不会改变原始数组

var arr = [1,2,3,4,5,6,7];
var newArr = arr.map(function(value, index, array){
    //参数一是:数组元素
    //参数二是:数组元素的索引
    //参数三是:当前的数组
    return value*4;
});
console.log(arr);//[1,2,3,4,5,6,7]
console.log(newArr);//[4,8,12,16,20,24,28]

6.3 数组方法filter过滤数组

filter() 方法创建一个新的数组,新数组中的元素是通过检查指定数组中符合条件的所有元素。

  var arr = [12, 66, 4, 88, 3, 7];
  var newArr = arr.filter(function(value, index,array) {
  	 //参数一是:数组元素
     //参数二是:数组元素的索引
     //参数三是:当前的数组
     return value >= 20;
  });
  console.log(newArr);//[66,88] //返回值是一个新数组

6.4 数组方法some

some 查找数组中是否有满足条件的元素 ,如果数组中有元素满足条件返回 true,否则返回 false。

只要查找到满足条件的一个元素就立马终止循环

 var arr = [10, 30, 4];
 var flag = arr.some(function(value,index,array) {
    //参数一是:数组元素
     //参数二是:数组元素的索引
     //参数三是:当前的数组
     return value < 3;
  });
console.log(flag);

6.5数组方法every

every() 方法用于检测数组所有元素是否都符合指定条件(通过函数提供

如果数组中检测到有一个元素不满足,则整个表达式返回 false ,且剩余的元素不会再进行

如果所有元素都满足条件,则返回 true。

注意: every() 不会对空数组进行检测。

注意: every() 不会改变原始数组。

var arr = [56, 32, 78, 11, 23, 103, 45, 103];
        // every() 方法用于检测数组所有元素是否都符合指定条件(通过函数提供)。
        var rel = arr.every(function (v) {
            console.log("zhixing");
            return v < 100
            // 如果数组中检测到有一个元素不满足,则整个表达式返回false,且剩余的元素不会再进行检测。
            // 所有元素都满足条件 才会返回true
        })
        console.log(rel);    //6次zhixing   false

6.6 数组方法find

find() 方法返回通过测试(函数内判断)的数组的第一个元素的值。

find() 方法为数组中的每个元素都调用一次函数执行:

  • 当数组中的元素在测试条件时返回 true 时, find() 返回符合条件的元素,之后的值不会再调用执行函数。

  • 如果没有符合条件的元素返回 undefined

 var arr = [56, 32, 78, 11, 23, 103, 45, 103];
        var rel = arr.find(function (v) {
            console.log("执行");
            return v > 100
        })
        console.log(rel);        //6次执行 103

 

6.7 数组方法reduce

reduce方法接收一个函数作为累加器,数组中的每个值(从左到右)开始缩减,最终计算为一个值。
        array.reduce(function (total, value, index, array) {
        - total 必需。初始值, 或者计算结束后的返回值。
          value 必需。当前元素 
          index 可选。当前元素的索引 
          array可选。当前元素所属的数组对象。 
        - initialValue 作为第一次调用 `callback`函数时的第一个参数的值。 如果没有提供初始值,则将使用数组中的第一个元素。
        }, initialValue)
 // 求和
        var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9];
        var rel1 = arr.reduce(function (total, value) {
            
            return total + value
            
        })
        console.log(rel1);  //45
    // 求最大值
        var arr2 = [45, 67, 12, 2, 103, 44, 33];
        var rel2 = arr2.reduce(function (total, value) {
            // if (total < value) {
            //     total = value;
            // }
            
            return Math.max(total, value);
        })
        console.log(rel2);    //103
    // 数组去重
        // splice  push()
        var arr3 = [44, 65, 44, 12, 3, 2, 5, 2, 16];
        var rel3 = arr3.reduce(function (total, value, index) {
            // []
            if (!total.includes(value)) {
                total.push(value);
            }
            return total;
        }, [])
        console.log(rel3);   //[44, 65, 12, 3, 2, 5, 16]

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值