Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

this、变量提升与原型链 #2

Open
791045873 opened this issue Nov 12, 2018 · 0 comments
Open

this、变量提升与原型链 #2

791045873 opened this issue Nov 12, 2018 · 0 comments

Comments

@791045873
Copy link
Owner

this

这里不展开讲如何判断this的指向,只记录一些会让自己疑惑的地方。
首先分享一个学习链接,this为什么如此设计

其次说一下箭头函数,箭头函数不会创建自己的this,它只会从自己的作用域链的上一层继承this。(从MDN抄来的定义)
看如下代码:

window.num = 1
const a = {
  num: 2,
 func: () => {
    console.log(this.num)
  }
}

a.func() //  1

上方的代码中箭头函数会自己绑定this,之前我一直疑惑为什么这个自动绑定的this不是指向a?

回顾一下最开始抄过来的定义,仔细看一下,发现了_作用域链_这几个字。而对象并不会产生作用域链,作用域是函数体产生的(虽然在es6中,循环的大括号里也会产生新的作用域)。所以上述代码里的箭头函数的上一级作用域链的this就是window,故箭头函数绑定了window作为他的this

变量提升

不展开细节,只记录一个小点。

所有的声明都是被提升到块顶部,var顶部申明同时初始化为undefined,let在顶部申明直到遇到let才进行初始化,function顶部申明同时初始化和赋值(不像let可以留空初始化为undefined),变量初始化之后才能进行其他操作,tdz就是这么来的(引用知乎上的一段话)

在“定义”任何一个变量时(这里的定义指我们var、let、const了一个变量),会进行两个步骤:声明、定义。
看如下截图:
image
第一次访问a时报错,是因为“暂时性死区”。
访问b为undefined,是因为var一个变量之后,该变量被提升且被初始化为undefined。
第二次let a报错,是因为之前已经declare了a,再次用let重复声明是不被允许的。这里也佐证了let会提升,因为如果不提升的话,报错的相关内容应该是console.log(a)的报错。

原型链

同样不记录相关细节。
梳理一下如何用一个工具函数Base.extend构造原型链。(Base理解为基类)
思考一下该工具函数的目标:

  • 可以在任意继承了Base的构造函数上调用extend
  • extend接受两个参数:1、扩展在原型链上的方法。2、放在构造函数本身上的静态方法
  • extend返回一个新的构造函数
   Base(){}
   Base.extend = function(protos, statics){
       const that = this
       const Func = function() {
          that.call(this)
       }
       Func.prototype = Object.create(that.prototype)
       Func.prototype.constructor = Func
       for(let a in props) {
           Func.prototype[a] = props[a]
        }
        for(let j in methods){
           Func[j] = methods[j]
        }
        Func.extend = that.extend
        return Func
    }

代码很简单,主要是要在写代码时明确自己要实现什么功能,输入输出是什么

Object.create

最后说一下Object.create这个API。(因为自己没怎么用过,所以在这里提一下)在MDN上的定义为:

Object.create()方法创建一个新对象,使用现有的对象来提供新创建的对象的__proto__。

用自己的话解释一遍就是:
Object.create会返回一个对象,可以该对象类比为构造函数new出来的实例对象。
由于“实例对象“是没法主动访问原型链的,即a.b,实例对象a的原型链上有方法b,但是b的查找工作只能交给js去做,开发人员并不能直接拿到b。(这里讲的有些含混)
为了解决这个问题,浏览器提供了我们一个API:proto
所以MDN关于Object.create的定义的后半句的意思是:用接收的参数给返回的对象构造一个原型链。即prototype所指向的对象为传递给create的第一个参数。(类似于实例对象的感觉)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant