JavaScript高级内容回顾第一天

内容回顾

一. this的绑定规则

1.1. 绑定规则

  • 默认绑定
    • 普通的函数被独立调用了
        function foo() {
        console.log("foo", this)
      }
      foo()  // window 
    
    • 函数定义在对象中, 但是独立调用
  // 2. 函数定义在对象中, 但是独立调用
  var obj = {
    name: "孙悟空",
    bar: function() {
      console.log("bar", this)
    }
  }

  var baz = obj.bar
  baz()   // 这种属于独立函数调用 this指向的是window
  • 高阶函数
   function test(fn) {
      fn()
    }
    test(obj.bar)
  • 严格模式下, 独立调用的函数中的this指向的是undefined
  "use strict"  // 这样写就是严格模式
  • 隐式绑定
    • JavaScript中的函数时可以当做一个类的构造函数来使用, 也就是使用new关键字
   function foo() {
      console.log("foo函数", this)
    }

    var obj = {
      bar: foo
    }

    obj.bar()
  • 显式绑定
   var obj = {
      name: "孙悟空"
    }

    function foo() {
      console.log("foo函数", this)
    }

    // 执行函数, 并且函数this指向obj对象
    // obj.foo = foo
    // obj.foo()


    // 执行函数. 并且强制this就是obj对象
    foo.call(obj)
    foo.call("abc")  // 包装类对象
    foo.call(123)    // 包装类对象
    foo.call(undefined)  // 默认没有包装类型绑定到window
  • new绑定
    1. 创建一个新对象
    2. 将this指向空对象
    3. 执行函数体中的代码
    4. 没有显示非空对象时, 默认返回这个对象
  function foo() {
      this.name = "孙悟空"
      console.log("foo函数", this)
    }

    new foo()

1.2. 显式绑定

  • apply/call
  • bind
  • JavaScript所有函数都可以使用call和apply方法
    • 第一个参数是相同的, 要传入一个对象
      • 这个对象的作用是什么呢? 就是给this准备的
      • 在调用这个函数时, 会将this绑定到这个传入的对象上
      • 后面的参数, apply为数组, call为参数列表
    function foo(name, age, height) {
      console.log("foo函数被调用", this)
      console.log("打印参数", name, age, height)
    }
    // apply
    foo.apply("apply", ["猪八戒", 28, 1.98])
    // acll
    foo.call("call", "沙和尚", 38, 2.18)
  • 如果我们希望一个函数总是显示绑定到一个对象身上, 可以怎么做呢?
    • 使用bind()方法, bind()方法创建一个新的绑定函数
    • 绑定函数是一个exotic function object(怪异函数对象 ECMAScript 2015中的术语)
   function foo(name, age, height, address) {
      console.log("foo函数", this)
      console.log("参数", name, age, height, address)
    }
    var obj = {name: "孙悟空"}
    // 2. bind函数的其他参数
    var bar = foo.bind(obj, "猪八戒", 28, 1.98)
    bar("沙悟净")

1.3. 内置函数的规则

  • 经验
  // 1. 定时器
    setTimeout(function() {
      console.log("定时器函数", this)  // window
    }, 1000)

    // 2. 按钮的点击监听
    var btnEl = document.querySelector("button")
    btnEl.onclick = function() {
      console.log("按钮的点击", this)  // btn
    }

    btnEl.addEventListener("click", function() {
      console.log("btnEl点击", this)  // btn
    })

    // 3. forEach 第二个参数绑定的this
    var names = ["abc", "bca", "nba"]
    names.forEach(function(item) {
      console.log("forEach", this)  // 有你好参数绑定的是String"你好"  没有就是window
    }, "你好")

1.4. 规则的优先级

  • new (优先级最高)

  • bind (其次)

  • apply/call (在其次)

  • 隐式绑定 (在其次)

  • 默认绑定 (最后)

    • new绑定优先级高于隐式绑定
      • new 不可以和apply和call一起使用
    • 显示绑定优先级高于隐式绑定
    • bind的优先级高于apply
    • bind的优先级高于call

1.5. 规则之外的情况

  • undefined/null
  • 间接函数引用(了解)
  • 如果在显示绑定中, 我们传入一个undefined或者null
    • 那么这个显示绑定会被忽略, 使用默认规则

    • 创建一个函数的间接引用, 这种情况使用默认绑定规则

      • 显示绑定使用null或者undefined使用的是默认绑定
    function foo() {
      console.log("foo函数", this)
    }

    foo.apply("abc")
    foo.apply(undefined)  // window
    foo.apply(null)
  • 间接函数引用
  var obj1 = {
      name: 'obj1',
      foo: function() {
        console.log("foo", this)
      }
    }
    var obj2 = {
      name: "obj2"
    };

    // obj2.foo = obj1.foo
    // obj2.foo()
    // 前面需要加上逗号. 
    ;(obj2.foo = obj1.foo)()  // window 默认绑定

二. 箭头函数的使用

2.1. 箭头函数的写法

  • 基本写法
  • 优化写法
    • 只有一个参数时, 可以省略()
    • 只有一行代码时, 可以省略{}
    • 只要一行代码时, 表达式的返回值会作为箭头函数默认返回值, 所以可以省略return
    • 如果箭头函数默认返回的是对象, 在省略{}的时候, 对象必须使用()包裹 () => ({name: “why”})
  // 箭头函数完整写法
  var foo3 = (name, age) => {
      console.log("箭头函数的函数体")
      console.log(name, age)
    }
  • 箭头函数练习
      // 箭头函数实现nums所有偶数平方和
      var nums = [20, 30, 11, 15, 111]
      var result = num.filte(item => item % 2 === 0)
                    .map(item => item * item)
                    .reduce((prvValue, item) => prvValue + item)
    

2.2. 箭头函数中的this

  • 箭头函数是没有绑定this
  • this的查找规则:
    • 去上层作用域中查找this
    • 直到找到全局this
  var bar = () => {
    console.log("bar", this)
    }
    bar() 
    通过apply调用也没有thisbar.apply("勇敢牛牛")
    var obj = {
      name: "obj",
      foo: () => {
        var bar = () => {
          console.log("bar", this)
        }
        return bar
      }
    }

    var fn = obj.foo()
    fn.apply("你好")

2.3. 箭头函数this应用

  • 模拟网络请求
  • 不好理解: 回调(好好理解一下)
    • 函数传来传去
    // 网络请求工具函数
    function requset(url, callback) {
      var result = ["abc", "cba", "nba"]
      callback(result)
    }

    // 实际操作业务代码
    var obj = {
      names: [],
      network: function () {
        // 1. 早期的做法
        // var _this = this
        // requset("/names", function(res) {
        //   _this.names = [].concat(res)
        // })


        // 2. 箭头函数写法
        requset("/names",  (res) => {
          this.names = [].concat(res)
        })
      }
    }

    obj.network()
    console.log(obj)

this面试题

  var name = "window";

var person = {
  name: "person",
  sayName: function () {
    console.log(this.name);
  }
};

function sayName() {
  var sss = person.sayName;
  sss();  // window 独立函数调用 默认绑定
  person.sayName();   // 隐式绑定: person
  (person.sayName)();  // 隐式绑定: prerson和上面一样 
  (b = person.sayName)(); // 间接函数引用 独立函数 ~window
}

sayName();
var name = 'window'

var person1 = {
  name: 'person1',
  foo1: function () {
    console.log(this.name)
  },
  foo2: () => console.log(this.name),  // 找上层作用域 因为 Person1是对象, 没有作用域 所以是window
  foo3: function () {
    return function () {
      console.log(this.name)
    }
  },
  foo4: function () {
    return () => {
      console.log(this.name)
    }
  }
}

var person2 = { name: 'person2' }

person1.foo1(); // 隐式绑定 person1
person1.foo1.call(person2); // 显示绑定 person2

person1.foo2(); // 上层作用域  window
person1.foo2.call(person2); // 因为没有this call绑定也没用  还是window 

person1.foo3()(); // 默认绑定: window
person1.foo3.call(person2)(); // 默认绑定: window
person1.foo3().call(person2); // 显示绑定: person2

person1.foo4()(); // person1
person1.foo4.call(person2)(); // person2
person1.foo4().call(person2); // person1
  var name = 'window'
function Person (name) {
  this.name = name
  this.foo1 = function () {
    console.log(this.name)
  },
  this.foo2 = () => console.log(this.name),
  this.foo3 = function () {
    return function () {
      console.log(this.name)
    }
  },
  this.foo4 = function () {
    return () => {
      console.log(this.name)
    }
  }
}
var person1 = new Person('person1')
var person2 = new Person('person2')

person1.foo1() // 隐式绑定 person1
person1.foo1.call(person2) // 显示绑定person2

person1.foo2() // 上层作用域person1
person1.foo2.call(person2) // person1

person1.foo3()() // 默认绑定 window因为拿到一个函数直接调用 相当于 fn()
person1.foo3.call(person2)() // 默认绑定: window
person1.foo3().call(person2) // 显示绑定 person2

person1.foo4()() // person1
person1.foo4.call(person2)() // 显示绑定person2
person1.foo4().call(person2) // 隐式绑定person1
  var name = 'window'
function Person (name) {
  this.name = name
  this.obj = {
    name: 'obj',
    foo1: function () {
      return function () {
        console.log(this.name)
      }
    },
    foo2: function () {
      return () => {
        console.log(this.name)
      }
    }
  }
}
var person1 = new Person('person1')
var person2 = new Person('person2')

person1.obj.foo1()() // 默认绑定: window
person1.obj.foo1.call(person2)() // 默认绑定window
person1.obj.foo1().call(person2) // 显示绑定 person2

person1.obj.foo2()() // 上层作用域 obj(隐式绑定)
person1.obj.foo2.call(person2)() // 上层作用域person2
person1.obj.foo2().call(person2) // 上层作用域 obj
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

coderyhh

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值