函数定义和调用及call apply bind用法理解

1、函数的定义和调用

1.1函数的3种定义方法

1.1.1 函数声明
//ES5
function getSum() {}
function () {}
//ES6
() => {}
1.1.2 函数表达式
// ES5
var sum = function() {}
//ES6 
let sum=() => {} 
1.1.3 构造函数
const sum = new Function('a', 'b', 'return a + b')

1.2 ES5中函数的4次调用

在ES5中函数内容的this指向和调用方法有关
1.2.1 函数调用模式
包括函数名()和匿名函数调用,this指向window
function getSum() {
   console.log(this) //这个属于函数名调用,this指向window
}
getSum()

(function() {
   console.log(this)  //匿名函数调用,this指向window
}) ()

var getSum = function () {
 console.log(this) // 实际上也是匿名函数调用 window
}
getSum()
1.2.2 方法调用
对象,方法名(),this指向对象
var objList = {
  name: 'methods',
  getSum: function() {
   console.log(this) //obList对象
  }
}
objList.getSum()
1.2.3 构造器调用
new 构造函数名()this指向实例化的对象
function Person() {
    console.log(this); //是构造函数调用,指向实例化的的对象personOne
}
var personOne = new Person();
1.2.4 间接调用
利用call和apply来实现,this就是call和apply对应的第一个参数,如果不传值或者第一个值为null,undefined时this指向window
function foo() {
    console.log(this);
}
foo.apply('我是apply改变的this值');
foo.call('我是call改变的this值')

1.3 ES6中函数的调用

箭头函数不可以当作构造函数使用,也就是不能用new命令实例化一个对象,否则会抛出一个错误 箭头函数的this是和定义时有关和调用无关 调用就是函数调用模式
(() = > {
	console.log(this) // windom
}) () 

let arrowFun = () => { 
	console.log(this) //windom
}
arrowFun ()

let arrowObj = {
    arrFun: function() {
       (() => {
           console.log(this)  //this 指向的是arrowObj对象
       }) ()
    }
}
arrowObj.arrFun();

1.4 call,apply和bind

call和apply可以调用函数,改变this,实现继承和借用别的对象的方法
1.4.1 call和apply理解
//例1
var name = '小王',age=17;
var obj={
  name:'小张',
  objAge: this.age,
  myFun:function(){
    console.log(this.name+"年龄"+this.age);//小张年龄 undefined
  }
}
console.log(obj.objAge);   //17
obj.myFun();
//例2
var fav='盲僧';
function shows(){
  console.log(this.fav);
}
shows() //盲僧
比较一下这两者 this 的差别,第一个打印里面的 this 指向 obj,第二个全局声明的 shows() 函数 this 是 window ;
1.call()、apply()、bind() 都是用来重定义 this 这个对象的!
如:
var name = '小王',age = 17;
var obj={
  name:'小张',
  objAge:this.age,
  myFun:function() {
    console.log(this.name+"年龄"+this.age);
  }
}
var db={
  name:'德玛',
  age:99
}
obj.myFun.call(db);   //德玛年龄99
obj.myFun.apply(db);  //德玛年龄99
obj.myFun.bind(db)(); //德玛年龄99
以上出了 bind 方法后面多了个 () 外 ,结果返回都一致!
由此得出结论,bind 返回的是一个新的函数,你必须调用它才会被执行。
2.对比call 、bind 、 apply 传参情况下
var name = '小王',age=17;
var obj={
  name:'小张',
  objAge:this.age,
  myFun:function(fm,t){
    console.log(this.name+"年龄"+this.age,"来自"+fm+"去往"+t);
  }
}
var db={
  name:'德玛',
  age:99
}
obj.myFun.call(db,'成都','上海');      //德玛年龄99 来自成都去往上海
obj.myFun.apply(db,['成都','上海']);   //德玛年龄99 来自成都去往上海
obj.myFun.bind(db,'成都','上海')();    //德玛年龄99 来自成都去往上海
obj.myFun.bind(db,['成都','上海'])();  //德玛年龄99 来自成都,上海去往undefined
微妙的差距!
从上面四个结果不难看出:
call 、bind 、 apply 这三个函数的第一个参数都是 this 的指向对象,第二个参数差别就来了:
call 的参数是直接放进去的,第二第三第 n 个参数全都用逗号分隔,直接放到后面 obj.myFun.call(db,‘成都’, … ,‘string’ )。
apply 的所有参数都必须放在一个数组里面传进去 obj.myFun.apply(db,[‘成都’, …, ‘string’ ])。
bind 除了返回是函数以外,它 的参数和 call 一样。
当然,三者的参数不限定是 string 类型,允许是各种类型,包括函数 、 object 等等!
1.4.2 call和apply的用法
1.间接调用函数,改变作用域的this值 2.劫持其他对象的方法
var foo = {
	name:"张三",
	logName:function() {
			console.log(this.name)
	}
}
var bar={
	name: “李四”
};
foo.logName.call(bar);//李四
实质是call改变了foo的this指向为bar,并调用该函数
3.在继承中的应用
function Person(name,age,love) {
    this.name=name;
    this.age=age;
    this.love=love;
    this.say=function say() {
      console.log("姓名:"+name);
    }
  }
  //call方式
  function student(name,age){
    Person.call(this,name,age);
  }
  //apply方式
  function teacher(name,love){
    Person.apply(this,[name,love]);
    //Person.apply(this,arguments); //跟上句一样的效果,arguments
  }
  //call与aplly的异同:  
  //1,第一个参数this都一样,指当前对象  
  //2,第二个参数不一样:call的是一个个的参数列表;apply的是一个数组(arguments也可以)
  var per=new Person("武凤楼",25,"魏荧屏"); //姓名:武凤楼
  per.say();
  var stu=new student("曹玉",18);          //姓名: 曹玉
  stu.say();
  var tea=new teacher("秦杰",16);          //姓名:秦杰
  tea.say();
4.将类数组形式转化为数组
// arguments
// 返回值为数组,arguments保持不变
var arg = [].slice.call(arguments);

// nodeList
var nList = [].slice.call(document.getElementsByTagName('li'));
function turnToArray(){
    var arrArgs = Array.prototype.slice.call(arguments) // 将参数转换成数组
    console.log.apply(console,arguments) // a b(打印出所有参数 )
    console.log(arrArgs) // ['a','b']
}
turnToArray('a','b')
5.合并数组
var array1=[1,3,5];
var array2=[54,"join"];
[].push.apply(array1,array2);
console.log(array1); // [1,3,5,54,join]
6.求数组最大值
var numbers = [1,13,-3];
var maxInNumbers = Math.max.apply(Math,numbers); // 13
maxNumber = Math.max.call(Math,1,13,-3);         // 13
7.判断字符类型
//isArray的源码
function ifArray(obj){
  return Object.prototype.toString.call(obj) === '[object Array]'
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值