call,apply,bind的实现原理及使用

本文详细介绍了JavaScript中call、apply和bind方法的使用,包括它们的相同点和不同点,以及如何利用它们进行伪数组转化、数组拼接、变量类型判断和实现继承。此外,还探讨了多继承的实现方式和作用域概念。
摘要由CSDN通过智能技术生成

前言:
js中的变量作用域
作用域指一个变量的作用范围
作用域分为全局作用域和函数作用域
全局作用域 页面打开时创建,关闭时被销毁(全局对象window)
函数作用域:
1.调用函数时,函数作用域被创建,函数执行完毕,函数作用域被销毁
2.在函数作用域中访问变量,会先在自身作用域中寻找,若没有找到会到函数的上层作用域中寻找,一直到全局作用域
3.在函数作用域中,不使用变量关键字声明,在赋值时会往上一级作用域寻找已经声明的同名变量,至到全局作用域时没有找到,则会成为window 属性

call apply bind

相同点

改变函数执行的上下文就是当执行一个方法的时候希望能够使用另一个对象来作为作用域对象

不同点

call

call和apply的差别在于参数的区别,call的第二个参数以参数列表的形式展现

apply

apply第二个参数以数组的形式展现

bind

事先先把fn的this改变为我们想要的结果,并把对应的参数值准备好,以后用到了直接执行即可,但和call,apply不同就是不会马上执行

常见面试题

将伪数组转化为数组

js的伪数组
(通过document.getElementByTagName获取的元素、含有length属性的对象,函数的参数arguments)具有length属性并且可以通过0,1,2…下标来访问其中元素,但没有Array的push,pop等方法。

case1: dom节点:
<div class="div1">1</div>
<div class="div1">2</div>
<div class="div1">3</div>

let div = document.getElementsByTagName('div');
console.log(div); // HTMLCollection(3) [div.div1, div.div1, div.div1] 里面包含length属性

let arr2 = Array.prototype.slice.call(div);
console.log(arr2); // 数组 [div.div1, div.div1, div.div1]

但是这个不适用IE6~8,会报错

解决方法 通过循环一个个加到数组中
for (var i = 0; i < oLis.length; i++) {
    ary[ary.length] = oLis[i];
}

Array.prototype.slice.call() 对于arguments对象和含有length的对象不存在 IE兼容问题

数组的拼接,添加

let arr1 = [1,2,3];
let arr2 = [4,5,6];

//数组的concat方法:返回一个新的数组
let arr3 = arr1.concat(arr2); 
console.log(arr3); // [1, 2, 3, 4, 5, 6]

console.log(arr1); // [1, 2, 3] 不变
console.log(arr2); // [4, 5, 6] 不变
// 用 apply方法
[].push.apply(arr1,arr2);  // 给arr1添加arr2
console.log(arr1); // [1, 2, 3, 4, 5, 6]
console.log(arr2); // 不变

判断变量类型

let arr1 = [1,2,3];
let str1 = 'string';
let obj1 = {name: 'thomas'};
//
function isArray(obj) {
  return Object.prototype.toString.call(obj) === '[object Array]';
}
console.log(fn1(arr1)); // true

//  判断类型的方式,这个最常用语判断array和object,null(因为typeof null等于object)  
console.log(Object.prototype.toString.call(arr1)); // [object Array]
console.log(Object.prototype.toString.call(str1)); // [object String]
console.log(Object.prototype.toString.call(obj1)); // [object Object]
console.log(Object.prototype.toString.call(null)); // [object Null]

利用call,apply做继承

function Animal(name){      
    this.name = name;      
    this.showName = function(){      
        console.log(this.name);      
    }      
}      

function Cat(name){    
    Animal.call(this, name);    
}      

// Animal.call(this) 的意思就是使用this对象代替Animal对象,那么
// Cat中不就有Animal的所有属性和方法了吗,Cat对象就能够直接调用Animal的方法以及属性了
var cat = new Cat("TONY");     
cat.showName();   //TONY

多继承

  function Class1(a,b) {
    this.showclass1 = function(a,b) {
      console.log(`class1: ${a},${b}`);
    }
  }

  function Class2(a,b) {
    this.showclass2 = function(a,b) {
      console.log(`class2: ${a},${b}`);
    }
  }

  function Class3(a,b,c) {
    Class1.call(this);
    Class2.call(this);
  }

  let arr10 = [2,2];
  let demo = new Class3();
  demo.showclass1.call(this,1); // class1: 1,undefined
  demo.showclass1.call(this,1,2); // class1: 1,2
  demo.showclass2.apply(this,arr10); // class2:2,2

参考资料‘:https://juejin.cn/post/6844903567967387656

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值