javascript对象、函数、构造函数、原型、作用域、闭包、this概论

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/flyfeifei66/article/details/83104955

1、对象

一切引用类型都是对象,函数function其实也是对象。对象多用字面量表示法创建。所有对象都是键值对的集合,这个值当然也可以是对象/函数,可以有很多层级,这个跟json有点像,在现代化js里,json和js对象可以无缝转换。

2、函数

函数是一种特殊的对象,函数名只是函数的一个指针,可以被当做变量传递,给编程带来极大的灵活性,比如回调。

3、构造函数

构造函数也是函数,约定首字母大写,但是不是必须的。

构造函数用于构造一个新的实例,但是如果函数中有返回实例的代码,那么直接返回该实例,否则返回创建的新实例。

创建对象的过程:首先创建一个空的obj,然后他的原型指向构造函数的原型,然后用新对象去call构造函数(改变this指向,指向obj),只要构造构造函数包含this.属性=值的代码,新的对象就会被添加属性;如果构造函数中没有this相关代码,返回的是一个空的obj,这就是普通function也能new的原因,但是意义不大。

4、原型

ES6之前JS都是没有继承的,原型也是一个实例,默认原型是Object对象的一个实例,拥有一些通用方法,比如toString。所有的引用类型创建时都会被指定一个默认原型,可以通过代码修改这个原型,指定为另一个具体的实例,依次指下去就可以形成一个链,就是原型链。所有同一类对象的实例的原型链是一样的,只有本示例的属性不同,所以原型实现了“代码的共享”,也模拟了继承。

但是ES6开始,JS有了class,有了extends,原型的写法没有必要了。个人认为原型是JS前期的设计不良,ES5、ES6一直在修正和优化JS。

5、作用域

作用域就是一个函数能访问的变量的范围,从自身函数代码覆盖的范围一直往上,最终都会到全局作用域(window),形成的链也叫作用域链。作用域其实跟很多高级语言原理一样,比较好理解。

6、闭包

闭包代码表现上往往是一个函数内包含另一个函数,子函数中有引用外层函数的局部变量,而这个子函数又被外界调用或者引用,就会“导致”局部变量不能被释放。

正常情况下,一个函数被调用,执行结束完局部变量就会被释放,但是闭包提供了一种保存“局部变量”的手段。

let:let关键字声明变量,同时会在最近的块中开辟块级作用域,并将该变量和该作用域绑定。而如果这个变量被一个函数引用(形参),只要这个函数不消失,这个变量和当前作用域就不会消失,从而形成一个闭包。

这就是在for循环中用let接收参数,然后给页面上的组件绑定方法时,形参不会出错乱的原因

7、this

this的指向在函数(非箭头函数)定义的时候是确定不了的,只有函数执行的时候才能确定this到底指向谁,实际上this的最终指向的是那个调用它的对象。它有如下三种情况:

情况1:如果一个函数中有this,但是它没有被上一级的对象所调用,那么this指向的就是window,这里需要说明的是在js的严格版中this指向的不是window,但是我们这里不探讨严格版的问题,你想了解可以自行上网查找。

情况2:如果一个函数中有this,这个函数有被上一级的对象所调用,那么this指向的就是上一级的对象。

情况3:如果一个函数中有this,这个函数中包含多个对象,尽管这个函数是被最外层的对象所调用,this指向的也只是它上一级的对象。

以上参考这里

ES6箭头函数

箭头函数表达式的语法比函数表达式更短,写法为:(参数1,参数2)=>{函数体},否则就得这么写function(参数1,参数2){函数体}

并且没有自己的this,arguments,super或new.target。这些函数表达式更适用于那些本来需要匿名函数的地方,并且它们不能用作构造函数。

箭头函数表达式对非方法函数是最合适的,不推荐作为obj的属性使用。

那么在箭头函数中写this.会指向谁?mozilla的解释是:箭头函数不会创建自己的this,它只会从自己的作用域链的上一层继承this

以下两个例子可以体会下,其中第一种是不推荐用的。

示例①:以下代码会输出33,11而不是33,22(obj对象处于全局作用域,因此say2从obj的作用域穿透到全局,打印11)

    var x = 11;
    var obj = {
      x: 22,
      methods: {
        x: 33,
        say: function () { console.log(this.x) },
        say2: () => { console.log(this.x) }
      }
    }

    obj.methods.say();
    obj.methods.say2();

示例②:以下代码会输出1,而不是100 

    var age = 99;

    function PersonX() {
      this.age = 0;
      setTimeout(() => {
        this.age++;
        console.log(age)
      }, 1000);
    }

    PersonX();

猜你喜欢

转载自blog.csdn.net/flyfeifei66/article/details/83104955