`

Javascript学习笔记 What's the "new"?

阅读更多

本文主要记录在学习Javascript(为了减少打字的工作量和读的顺口,以后会使用JS)的过程中,对于“var o = new Obj(1);”这行代码的理解。

在学习和使用JS之前,我学习过一些经典的编程语言,如Java、PHP和C,我可以熟练的使用Java,能够阅读和简单地编写C和C++的代码。

但是当我带着这些经验来接触JS的时候,我发现事情完全变化了,我在很长一段时间内只能用JS实现页面的功能,但是对于类以及类的实例化完全摸不到头脑。

我想这种错误产生于两个原因:
对于JS的学习,我是边工作边学习的,这样学的好处是上手快,缺点也同样显著:基础知识一塌糊涂;
很多JS的知识来源于互联网,网上有很多人自己也是一知半解(当然也包括本文和本文的作者),我看完之后再加上自己的理解,于是我距离真相越来越远了。
言归正传,要理解var o = new Obj(1);,我们首先要知道这条语句是干嘛的?

有过面向对象学习经验的人一定了解,这条语句是类的实例化。

一、要有类和实例化的知识

那么,什么是类,什么又是实例化?

维基百科给了一个比较抽象的定义:类的更严格的定义是由某种特定的元数据所组成的内聚的包。它描述了一些对象的行为规则,而这些对象就被称为该类的实例。

说的具体一些,类就是一些有相同个体的特征抽象,而逆着抽象,从而建立类到个体的过程叫做实例化。

比如中国人就可以作为一个类,每个人中国人都有一个中文名字,这就是类的一个属性。中国人的名字是什么,我们是说不出来的,但作为一个中国人的实例,我的名字是“山谷”。

这是很浅显的知识,尤其是对于计算机知识扎实的人。

二、JS中如何创造类

那么我们来看一段JS代码,JS是如何建立一个类。

var Obj = function(x) {
    this.x = x;
    console.log(this.x);
    //xxxxxxx
};

这是很标准的写法(包括缩进为4个空格而不是一个tab,每行结尾处都没有空格),的确,在JS中,一个Obj的类,就诞生了。

对于没接触过编程的小白还好办,我就这么记忆了,但是有Java或者C++书写经历的人一定会疯掉的,这是函数的声明方法,是的,在JavaScript 2.0之前,JS里面没有“类”(此话是David Flanagan在《JavaScript权威声明》中说的,我特此发表免责声明,由于他在好几个版本都保留了这句话,我假定这句话是真的)。

JS只有“伪类”,没有任何一个JS的结构是类(我们有对象,我们有数组,我们还有函数,我们就是没有类),但是JS可以模仿类,即类有什么,我们就有什么。

那么,类有什么?

类有属性(public、protected、private都行),类还有方法(不管静态的还是动态的),一般情况下,类还有构造函数。

仅以Java为例,我们写一个类看看吧。

public class Obj {
    public int i = 0;//属性
    private int x = 1;//属性

    public Obj(x) { //构造函数
        this.x = x;
    }

    public int getX() { //方法
        return this.x;
    }
}

那么JavaScript都可以模仿。

首先说JavaScript的构造函数,就是Obj这个function(用英文方便上下文对照)。

那么属性和方法可以怎么办,我们会尝试Obj.xxx这个方式,但事实证明,当var o = new Obj(),o是无法调用xxx的。

带着问题(问题是方法和属性挂载的位置),我们开始实例化吧!

三、实例化总共分三步(和把大象装到冰箱里的步骤一样多)

第一步:var o = {};
第二步:o.__proto__ = Obj.prtotype;//Obj.prototype?我们并没有声明prototype,对,这是浏览器自动加入的。
第三步:Obj.call(o, 1, 2);

总结为:第一步,创建一个空对象并赋值给o;第二步是定义原型链使得o指向Obj的原型对象;第三部为用对象o调用Obj函数,调用参数为1和2。

第一步好理解,既然是实例化,就要实例化类为对象,则o必然是一个对象,先赋值成对象,再进行操作。
第二步的难点在于什么是原型链,为什么原型链要o指向Obj的原型对象,那么Obj的原型对象又是什么?
第三步相对于第二步好理解,唯一的一点是call究竟干了什么?

3.1 原型链
根据ECMAScript的解释:每个由构造器创建的对象,都有一个隐式引用 ( 叫做对象的原型 ) 链接到构造器的“prototype”属性值。再者,原型可能有一个非空 (non-null) 隐式引用链接到它自己的原型,以此类推,这叫做原型链。
o.__proto__指向的是o原型链的上级,而其上级的__proto__由指向上级的上级,当使用对象o的一个方法时,如o.xx,js的解析器会沿着o的原型链一直向上寻找,找到最近的一个xx方法,然后调用。
通俗讲,就是通过这个方式,o可以调用Obj原型上的方法。
值得强调的是,o.__proto__并不具有通用性,目前Chrome、Firefox和Safari支持这一属性。

3.2 原型对象
原型对象也可以叫做原型。ECMAScript的定义很简单: 为其他对象提供共享属性的对象。
就JS的类来讲,原型可以理解为挂载变量和方法的容器。
譬如,我们希望在Obj类中添加getS的方法,常规写法是:
Obj.prototype.getS = function() {
    //xxxxxxxxxxx;
};
但是为了方便长时间使用Java和C++的人理解,我们也可以写为:
Obj.prototype = {
    getS: function() {
        //xxxxxxxxxxxxxxxxxxx;
    }
}

3.3 o.__proto__ = Obj.prototype
理解了2.1和2.2,我们就明白了o.__proto__ = Obj.prototype是干嘛的了。
第二步是使Obj上的方法和变量可以为o所用。

3.4 第三步的重点: Obj.call(o, 1, 2)
如果有面向对象的知识的话,可以推出知道,这一步要执行Obj的构造函数。
的确,这一步是由call方法完成的。

那么,call是做什么的?
若有A.call(B, C),则是对象B使用参数C执行A方法,如果你这么回答,似乎是正确的。但我们要向更深处走一步:在执行完call之后,对于A、B、C分别有什么影响。

首先很好理解的是A和C,A使用了C参数,执行了自己,那为什么不直接写A(C),就是为了酷吗?
答案时否定的,若A中有关于this的修改,则this不再指向A原来所在的域,而是指向B。

如下所示:
var A = function(C) { C++; console.log(C); };
var B = {D: 2};
var C = 1;
var D = 1;
这时A.call(B, C);和A(C);是没有区别的。
但是如果A的实现如下所示。
var A = function() { console.log(this.D + C); }
A.call(B, C)的结果就是输出3,而A(C)的结果就是2。

理解了call,我们就能明白Obj.call(o, 1, 2)是做什么的了。
函数Obj(也是类Obj的构造函数),得到了两个输入1和2,再将这两个值赋值给this.x和this.y,最后,将this指向o。

可以思考的问题是为什么属性和方法要挂接到Obj.prototype而不是Obj上?

以上是一些非常肤浅的理解,要解答原型链和原型的很多问题,是需要了解JS的发展历史和浏览器的内核实现,但就工程本身,理解到这里应该可以应付大部分关于类和声明开发了(当然你还有JS的语法知识和算法知识)。

 

分享到:
评论

相关推荐

    HTML+CSS+JavaScript教程学习笔记.zip

    HTML+CSS+JavaScript教程学习笔记HTML+CSS+JavaScript教程学习笔记 HTML+CSS+JavaScript教程学习笔记HTML+CSS+JavaScript教程学习笔记 HTML+CSS+JavaScript教程学习笔记HTML+CSS+JavaScript教程学习笔记 ...

    JavaScript学习笔记

    ### JavaScript面向对象基础 #### 创建对象 在JavaScript中,创建对象是进行面向对象编程的基础之一。不同于C#等其他语言,JavaScript提供了多种方式来创建对象。最常见的方式是使用`new Object()`或直接通过对象...

    Javascript学习笔记PPT

    Javascript学习笔记PPTJavascript学习笔记PPTJavascript学习笔记PPTJavascript学习笔记PPTJavascript学习笔记PPTJavascript学习笔记PPTJavascript学习笔记PPTJavascript学习笔记PPTJavascript学习笔记PPTJavascript...

    javascript学习笔记讲解版参考.pdf

    JavaScript学习笔记讲解版参考.pdf是一份详尽的教程,涵盖了从基础到进阶的JavaScript知识。这份笔记首先从CSS样式表开始,引导读者理解网页样式的设置与应用。 1. CSS(Cascading Style Sheets)样式表是用于控制...

    JavaScript学习笔记.pdf

    JavaScript学习笔记是一本关于JavaScript编程语言的教材,该教材通过丰富的实例,系统地介绍了JavaScript的基础知识和实际应用技巧,帮助读者一步步掌握客户端编程技术。本书共分为九章,每一章都有其特定的主题,...

    javascript笔记 javascript笔记

    <a href="javascript:prompt('What is your name?')">Click ``` - **解释:** 用户点击链接后会弹出一个输入对话框让用户输入名字。 ### JavaScript与DOM操作 JavaScript可以用来动态地修改文档对象模型(DOM),...

    前端学习笔记网站(HTML5+CSS3+JavaScript前端网页web课程设计).rar

    前端学习笔记网站(HTML5+CSS3+JavaScript前端网页web课程设计).rar前端学习笔记网站(HTML5+CSS3+JavaScript前端网页web课程设计).rar前端学习笔记网站(HTML5+CSS3+JavaScript前端网页web课程设计).rar ...

    我的javascript学习笔记

    根据提供的文件信息,可以看出这份“我的javascript学习笔记”主要涵盖了JavaScript中的几个关键概念和技术要点,包括正则表达式、AJAX以及一些JavaScript的核心语言特性。接下来将这些知识点进行详细的整理和解释。...

    Javascript学习笔记(传智播客视频学习笔记+代码)

    "Javascript学习笔记(传智播客视频学习笔记+代码)"是一份全面介绍JavaScript基础知识的学习资源,适用于初学者。这份笔记结合了传智播客的web前端培训视频内容,提供了丰富的理论讲解和实践代码,帮助读者从零开始...

    JavaScript 学习笔记集和代码库

    这个“JavaScript学习笔记集和代码库”涵盖了该语言的基础知识、进阶技巧以及实用示例,对于想要深入理解和掌握JavaScript的初学者或有经验的开发者来说,都是一个宝贵的资源。 首先,让我们来讨论JavaScript的基础...

    javascript学习笔记

    javascript学习笔记

    JavaScript 入门 新手学习笔记

    这篇"JavaScript入门新手学习笔记"提供了全面的学习资源,适合初学者系统性地掌握这一技术。 笔记可能包含了以下关键知识点: 1. **基础语法**:JS的基础包括变量(var、let、const)、数据类型(如字符串、数字、...

    JavaScript学习笔记-适合初学者

    本学习笔记专为初学者设计,旨在帮助新接触JavaScript的人快速掌握这门语言的核心概念和实用技巧。 首先,"JavaScript特效.chm"可能是一份关于JavaScript实现的各种网页特效的教程。这些特效可能包括图片轮播、下拉...

    javascript和jquery学习笔记

    javascript和jquery的学习笔记,自己做的大家可以下载浏览,很不错

    文档库,学习笔记,包括但不限于HTML、CSS、JavaScript.zip

    文档库,学习笔记,包括但不限于HTML、CSS、JavaScript 文档库,学习笔记,包括但不限于HTML、CSS、JavaScript 文档库,学习笔记,包括但不限于HTML、CSS、JavaScript 文档库,学习笔记,包括但不限于HTML、CSS、...

    尚硅谷JavaScript高级学习笔记

    尚硅谷JavaScript高级学习笔记

Global site tag (gtag.js) - Google Analytics