1. this 指向
普通函数中的 this 指向调用它的那个对象。这个和作用域是相反的。
// 声明位置 var me = { name: 'xiuyan', hello: function() { console.log(`你好,我是${this.name}`) } } var you = { name: 'xiaoming', hello: function() { var targetFunc = me.hello targetFunc() } } var name = 'BigBear' // 调用位置 you.hello() -结果:'BigBear' -原因:因为调用 hello 的时候它所在的对象是 you,所以它内部的 this 会指向 you,但是在它内部调用 targetFunc 的时候没有加 this,所以这个函数相当于 window 调用的,所以是 'BigBear'
特殊情况下的 this 指向,以下几种都会指向 window
- 立即执行函数
- setTimeout 中传入的函数
- setInterval 中传入的函数
如果改变 this 的指向
- 箭头函数:this 指向书写它的位置
var name = 'BigBear' var me = { name: 'xiuyan', // 声明位置 hello: () => { console.log(this.name) } } // 调用位置 me.hello() // BigBear
- 构造函数,指向新构建的对象
- bind、call、apply 重新定义 this 的指向。其中 bind 不会运行函数,只改变 this,其他两个都会执行函数,并返回结果。apply 的第二个参数是数组,其他两个都和原函数的参数一样。
2. 实现 bind、call、apply
- 特点:所有函数都可以继承;改变了 this
实现 call:相当于在当前的 obj 上加了一方法,这个方法的实现是要改变内部 this 的函数,执行完从这个 obj 上删除该方法就可
Function.prototype.myCall = function(context, ...args) { if (context === null || context === undefined) { context = typeof window === 'undefined' ? global : window } let key = Symbol('fn'); context[key] = this; // this 是我们要运行的函数 const res = context[key](args); delete context.func; return res; }
实现 bind:bind 生成一个函数,函数的调用分为 new 和 直接调用两种。
Function.prototype.myBind = function (context, ...args) { if (typeof this !== 'function') { thow new TypeError('not a funtion') } let self = this; function resultFn (...args2) { if (this indtanceof resultFn) { // 如果是 new 的形式绑定函数 return new self(...args, ...args2) } return self.call(context, ...args, ...args2) } resultFn.prototype = Object.create(self.prototype) return resultFn }
3. 执行上下文
全局上下文:全局代码所处的环境,不在函数中的代码都在全局执行上下文中
- 创建时机:在进入脚本时,只创建一次
创建阶段:
- 创建全局对象、this,并将 this 指向全局对象
- 给变量和函数安排内存空间
- 给变量赋值 undefined,将函数声明放入内存
- 创建作用域链
- 执行阶段:执行代码
函数上下文:在函数调用时创建的上下文
- 创建时机:函数调用时
创建阶段:
- 创建参数对象、this,将 this 指向调用它的对象
- 其他同全局上下文
- 代码执行完毕,函数上下文的生命周期久结束了,既出栈。
- eval 执行上下文:开发中不要使用
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。