深入浅出javascript原型和闭包

javascript原型和闭包,一直是javascript中比较难理解的两个部分,却又非常重要、非常基础,也是与其他主流面向对象语言的最大区别。这部分网上教程遍地都是,水平也是层出不穷,但是真正能说对、而且说的透彻的非常少,为了不被复制粘贴的水军搞晕,所以还是按自己的思路整理了一套。

目的是为了用最简单的语言描述清楚这两个重要且基础的概念。如果你是个其他语言的开发,看了这个教程能明白,那我的目的就达到了。

1.简单概述

其实,“原型和闭包”,只是一种简单的称呼,真正要理解的,不是“原型和闭包”,而是“原型链”和“作用域链”。原型和闭包没什么关系,但是又有那么一点点的类似。有很多人也在这个问题上混淆

简单来讲,
闭包作用域链)说的是变量在某个场景下的取值问题。
原型原型链)说的是变量的属性在某个场景下的取值问题。

当然这里我只是简单的用变量这个词,为的是让大家把关注点放在这两个关键概念的四个关键词和他们的区别上。但是其实在js中,一切都是对象

2.闭包

1、说到闭包一定要提到上下文作用域。这两个概念也十分类似,经常容易混淆。在我们开始执行一个函数之前,上下文帮我们做了很多铺垫。而作用域却是一个静态的概念,在函数创建的时候就已经确定好了。
2、同一个作用域,每次都会创建不同的上下文。它们的关系类似淘宝上同一套衣服(scope),模特的图片和买家秀(不同的execution context)可能差别很大也可能差不多。
3、大家一般说的闭包,都是纠结自由变量的取值。那么其实很简单,一句话,即,要到创建这个函数的那个作用域链取值,而不是调用父作用域
4、为了能够到创建的作用域中取值,必须暂时不销毁创建时候的上下文,即便已经执行完毕。所以闭包会增加内存开销。
5、函数作为返回值,函数作为参数传递时,就会产生闭包。
一个比较经典的栗子:

1
2
3
4
5
6
7
8
9
function a() {
var i = 0;
function b() {
alert(++i);
}
return b;
}
var c = a();
c();

这个闭包里面,a的上下文一直没有销毁,每次调用c(),都可以使i自增。

3.原型

说到原型归根到底就是要讨论下Object和Function(还有根源对象和内置函数),不过这个篇幅太大,我还是稍后做个专栏,现在我们还是讨论下比较表面的问题。
一个对象的大致创建过程,和它的属性a,我们是如何对其定义和取值的。
1、新建一个对象并赋值给变量a1:var a1 = {};
2、把这个对象的[[Prototype]]属性指向函数A的原型对象:a1.[[Prototype]] = A.prototype
3、调用函数A,同时把this指向1中创建的对象a1,对对象进行初始化:A.apply(a1,arguments)
我们找属性a的时候,通过对象的[[Prototype]]保存对另一个对象的引用,通过这个引用往上进行属性的查找,这就是原型链。
还是等有空把Object和Function讲一下吧,原型链这部分说的太浅显了。

refer

深入理解javascript原型和闭包(完结)
JavaScript概念总结:作用域、闭包、对象与原型链
JavaScript原型和继承
js闭包(转载)
javascript Prototype constructor的理解(一)

Contents
  1. 1. 1.简单概述
  2. 2. 2.闭包
  3. 3. 3.原型
  4. 4. refer
|