4 JS函数(arguments和this、绑定bind)

JS的三座大山:原型链 、this、 AJAX

arguments和this

每个函数都有,除了箭头函数(新语法)

1.arguments

  • 是包含所有参数的伪数组
    没有数组共有属性(push、pop)的就是伪数组
  • 代码
function fn(){
  console.log(arguments)
}
fn()

在这里插入图片描述

  • 如何传arguments
    1.调用fn即可传arguments
    2.fn(1,2,3)那么arguments就是[1,2,3]的伪数组
    因为给定参数后,发现是一个数组,但是没有数组的共有属性,因此是一个伪数组
    在这里插入图片描述
  • Array.from():可以把任何不是数组的东西变成数组

2.this

  • 代码
function fn(){
  console.log(this)
}
fn()
  • 如果不给任何的条件,那么this默认指向Window(这个不常用,直接用Window就好了)
    在这里插入图片描述
  • 如何传this
    目前可以用 fn.call()this
  • 如果传的this不是对象,那么JS会自动帮你封装成对象
    传数字1,就会变成对象1
    undefined,就会变成全局变量 window
    在这里插入图片描述
  • 当传fn.call(xxx,1,2,3)时,xxx会被自动转化为对象,而后面的1,2,3就是arguments
    call的参数被分成两段
    在这里插入图片描述
  • 如何取消封装:传什么就想要什么
    加一行代码:在声明中加'use strict'
    这样传的是什么,this就是什么
    在这里插入图片描述

3.结论
this是隐藏参数,arguments是普通参数
this是一种参数

4.假设没有this

例1

let person = {
  name: 'frank',
  sayHi(){
    console.log(`你好,我叫` + person.name)//此处直接用了person
  }
}

4.1 分析

  • 其中第四行:没有完成声明就直接用了对象person是合法的
    因为:console.log是一个函数,函数在此处还没有被调用,等调用的时候就person已经存在了
  • 因此:可以用直接保存了对象地址的变量获取'name'
  • 把这种方法简称为引用:一个变量保存了某个东西的地址

4.2 问题一

  • 函数和变量名绑定在一起了,如果person改名,另一边没改,那么sayHi函数就挂了
  • 如果先声明函数,其中要用到这个变量还没有声明,那如何确定变量名是个问题
  • sayHi函数甚至可能出现在另一个文件里面
  • 所以我们不希望sayHi函数里面出现person的引用

4.3 问题二:对象还好,如果用类问题更大

class Person{ //声明一个person的类
  constructor(name){
    this.name = name 
    // 这里的 this 是 new 强制指定的
  }
  sayHi(){
    console.log(???)
  }
}
  • 这里只有类,还没创建新对象 person,故不可能获取 person 的引用

5.需要一种办法拿到对象
这样才能获取对象的name属性
怎么在不知道一个对象的名字的情况下拿到一个对象的引用

5.1一种土方法,用参数
形参是可以代表一个东西的,如函数的x、y可以代表将要传进来的实际参数1和2

  • 对象
let person = {
  name: 'frank',
  sayHi(p){
    console.log(`你好,我叫` + p.name)
  }
}
person.sayHi(person)//person对象传给了函数
class Person{
  constructor(name){ this.name = name }
  sayHi(p){
    console.log(`你好,我叫` + p.name)
  }
}
person.sayHi(person)
  • 在每一个函数前面的第一个参数上,加了一个参数,并且约定这个参数就是到时候的新对象
  • Python用的就是这种方法,两步
    1.sayHi函数接受一个默认的参数self
    2.当你调用sayHi的时候,会故意复制一份person放到括号内,这样self.name就是person.name
    于是:person.sayHi()等价于person.sayHi(person)(Python偷偷帮你传对象)
    在这里插入图片描述

6.JS如何解决这个问题

6.1 JS没有在sayHi那里加一个参数,而是直接加了一个关键字,也就是this

  • JS在每个函数里加了this
  • 在任何函数里面可以用this去获取那个目前你还不知道名字的对象
let person = {
  name: 'frank',
  sayHi(){ //这里相当于省掉了一个this,等价于 sayHi(this)
    console.log(`你好,我叫` + this.name)
  }
}
person.sayHi()
  • person.sayHi()等价于person.sayHi(person)
  • 第三行的sayHi()括号中有一个隐藏的this,相当于sayHi(this)
  • 然后person就被传给了thisperson是个地址)
  • 这样,每个函数都能用this获取一个未知对象的引用了

总结

  • 我们想让函数获取对象的引用(对象名不知道,但我们知道它肯定存在)
  • 但是并不想通过变量名做到
  • Python通过额外的self参数做到
  • JS通过额外的this做到
    person.sayHi()会把person自动传给sayHi(传地址),sayHi可以通过this引用person
  • 其他
    注意person.sayHiperson.sayHi()的区别
    注意person.sayHi()的断句:(person.sayHi)()

7.引出另一个问题

  • person.sayHi(对)
  • person.sayHi(person)(错)
  • 为什么省略的格式是对的,完整的形式反而是错的

7.1解决问题:两种调用

  • 小白调用法
    person.sayHi
    会自动把person传到函数里,作为this
  • 大师调用法
    person.sayHi.call(person)
    需要手动把person传到函数里,作为this
    其中call是传递this的方法,传什么,this就是什么

8.大师调用法
JS出了一个新的调用方法callcall会使得所有东西明朗起来

  • person.sayHi.call(person)

  • call后面传什么,this就是什么
    person.sayHi.call({name:'jack'})传递一个对象,那么this就是一个对象,this.name就是jack

  • 相当于:把一个函数放到对象上面,但这个函数和这个对象没有任何关系,只是恰好出现在一起而已
    在这里插入图片描述

  • 好处:使用call调用的好处是,多了很多细节(我们推荐使用这个!)
    在这里插入图片描述

例2、不用this

  • 调用call时,即使用不到this,也要找个东西占位(一般用undefined),否则会默认参数第一个为this
    在这里插入图片描述

例3、用this(数组的隐藏函数中forEach就含有this
这个函数的作用:遍历当前数组
this就是当前数组,待传递

Array.prototype.forEach2 = function(fn){//是forEach的源代码
  for(let i=0; i<this.length; i++){
   fn(this[i],i )
  }
}

array.forEach2.call(array,(item)=>console.log(item))

意思是forEach2等于一个函数(这个函数接收另一个函数fn),然后遍历this,对于this里面的每一项,调用fn,同时传递一个i
在这里插入图片描述

  • this一定要是数组吗?
    不一定,还可以是自己写的伪数组,,因此this就是可以任意指定的参数而已
    Array.prototype.forEach2.call({0:'a',1:'b',length:2})
    在这里插入图片描述

9.this传递的两种方法

  • 隐式传递(相当于不管调用了什么函数,都传递了this
    fn(1,2) 等价于 fn.call(undefined, 1, 2)
    obj.child.fn(1) 等价于 obj.child.fn.call(obj.child, 1)对象的属性的里面的函数,就是把fn全面的整个部分作为this
  • 显示传递
    fn.call(undefined,1,2)
    fn.apply(undefined,[1,2])只是后面的参数要传数组而已

10.绑定this

  • 使用.bind可以让this不被改变
    f2绑定了this的值,传的时候就只需要传递 p1 和 p2 的值
function f1(p1, p2){
  console.log(this, p1, p2)
}
let f2 = f1.bind({name:'frank'})
// 那么 f2 就是 f1 绑定了 this 之后的新函数
f2(1,2) // 等价于 f1.call({name:'frank'})
  • .bind还可以绑定其他参数
    就是 f3 已经绑定了 this 和 p1 的值是什么,传递的时候只需要传 p2
let f3 = f1.bind({name:'frank'}, 'hi')
f3(1) // 等价于 f1.call({name:'frank'}, hi)
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值