搜索
首页web前端js教程Javascript 中的类和闭包_js面向对象

有人说javascript也是面向对象的,只是它是prototype based,当然这只是概念上的区别,我不想讨论js是不是面向对象的,关键是想说明虽然javascript的类表现得很像其他语言中的类,但是内部的实现机理确不太一致,如果一味的把javascript中的类类比作其他语言中的类,有时候脑子会犯混。

先看一段简单的代码,一般教材上介绍如何新建一个类的时候都是这样的(当然还有更复杂的方法,不过本质上是一样的):

复制代码 代码如下:

function MyClass(x) {
this.x = x;
}
var obj = new MyClass('Hello class');
alert(obj.x);

毫无疑问,此时obj具有一个x属性,现在的值是 Hello class. 但是,obj到底是什么?MyClass仅仅是一个函数而已,我们称之为构造函数。在其他OO的语言中,构造函数是要放在class关键字内部的,也就是先要声明一个类。另外,函数体内的this又是什么?其他OO语言中,this的概念是很明确的,就是当前对象,因为它在构造函数执行之前已经声明了类,类的内部的一些字段都是已经定义好的。

先解释下,在javascript的函数中,this关键字表示的是调用该函数的作用域(scope),作用域的概念也不是太好理解,下面再解释。不过可以简单的认为它是调用函数的对象。再看MyClass函数,它内部的this是什么呢?

如果我们把代码改成:
复制代码 代码如下:

var obj = MyClass('Hello class');

这是完全合乎语法的。如果这段代码是在浏览器中运行的,调试一下可以发现,this是window对象。而和obj没有任何关系,obj还是undefined,alert也不会有结果。原来的代码之所以可以工作,都是new关键字的功劳。new关键字把一个普通的函数变成了构造函数。也就是说,MyClass还是一个普通的函数,它之所以能构造出一个obj,基本上是new的功劳。当函数之前有new关键字的时候,javascript会创造一个匿名对象,并且把当前函数的作用域设置为这个匿名对象。然后在那个函数内部引用this的话就是引用的这个匿名对象,最后,即使这个函数没有return,它也会把这个匿名对象返回出去。那么obj自然就具有了x属性。

现在这个MyClass已经有点像一个类了。但是,这并不是new的工作的全部。Javascript同样可以方便的实现继承——依靠是prototype.prototype也是一个对象,毕竟除了原始类型,所有的东西都是对象,包括函数。更为重要的是,前面提到javascript是prototype based,它的含义就是在javascript中没有类的概念,类是不存在的,一个函数,它之所以表现的像类,就是靠的prototype. prototype可以有各种属性,也包括函数。上一段说的new在构造对象的过程中,在最终返回那个匿名对象之前,还会把那个函数的prototype中的属性一一复制给这个对象。这里的复制是复制的引用,而不是新建的一个对象,把内容复制过来,在其内部,相当于保留了一个构造它的函数的prototype的引用。有些教材含糊的说所有的“所有对象都有一个prototype属性”,这种说法是不确切的,虽然它内部确实有一个prototype属性,但是对外是不可见的。只有函数对象是有prototype属性的,函数对象的prototype默认有一个constructor属性。

看如下的代码:
复制代码 代码如下:

function MyClass(x) {
this.x = x;
}
var proObj = new MyClass('x');
InheritClass.prototype = proObj;
MyClass.prototype.protox = 'xxx';
function InheritClass(y) {
this.y = y;
}
var obj = new InheritClass('Hello class');
MyClass.prototype.protox = 'changed';
proObj.x = 'Changed Too';
alert(obj.protox);
alert(obj.x);

输出的结果是changed和Changed Too。此代码说明了对象内部保留的是构造函数的prototype的引用,要注意的是,proObj中也是保留的它的构造函数的prototype的引用。如果把代码改成:
复制代码 代码如下:

var obj = new InheritClass('Hello class');
proObj.protox = 'I am winner';
MyClass.prototype.protox = 'changed';
proObj.x = 'Changed Too';
alert(obj.protox);
alert(obj.x);

输出的就是 I am winner 和 Changed Too了。事实上,这些prototype逐层引用,构成了一个prototype链。当读取一个对象的属性的时候,首先寻找自己定义的属性,如果没有,就逐层向内部隐含的prototype属性寻找。但是在写属性的时候,就会把它的引用覆盖掉,是不会影响prototype的值的。
再介绍闭包,首先说明下,这里的闭包(closure)和离散数学中关系的传递闭包中的不是一个概念,我曾以为他们之间有关联,后来仔细想想,似乎并无什么关联,恰好名字一样而已。先看定义:
Closure
A "closure" is an expression (typically a function) that can have free variables together with an environment that binds those variables (that "closes" the expression).
要完全理解闭包需要对Javascript函数的机理有比较透彻的理解,而这个机理有点复杂,并不是三言两语能讲清的,有兴趣的朋友可以看这里 Javascript clousures. 即使是这篇文章,也只是大概讲了下原理。大意就是任何一个函数调用都在一个运行上下文(Execution Context)中执行的,这个上下文中有一个作用域对象,其中包括了这个函数的局部变量、参数等。另外,如果一个函数是一个内部函数,它的作用域中含有它外部函数的作用域。在内部函数遇到一个变量名的时候,它是从内部的作用域找起,不断往外层的作用域找。因此,如果内部函数作为一个对象返回出外部函数的时候,即使外部函数已经执行完毕,但是由于其内部函数仍有引用指向它,内部函数不会被释放,因为内部函数有外部函数的作用域,因此外部函数的局部变量也不会被释放。这就构成了闭包。
声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
Python vs. JavaScript:学习曲线和易用性Python vs. JavaScript:学习曲线和易用性Apr 16, 2025 am 12:12 AM

Python更适合初学者,学习曲线平缓,语法简洁;JavaScript适合前端开发,学习曲线较陡,语法灵活。1.Python语法直观,适用于数据科学和后端开发。2.JavaScript灵活,广泛用于前端和服务器端编程。

Python vs. JavaScript:社区,图书馆和资源Python vs. JavaScript:社区,图书馆和资源Apr 15, 2025 am 12:16 AM

Python和JavaScript在社区、库和资源方面的对比各有优劣。1)Python社区友好,适合初学者,但前端开发资源不如JavaScript丰富。2)Python在数据科学和机器学习库方面强大,JavaScript则在前端开发库和框架上更胜一筹。3)两者的学习资源都丰富,但Python适合从官方文档开始,JavaScript则以MDNWebDocs为佳。选择应基于项目需求和个人兴趣。

从C/C到JavaScript:所有工作方式从C/C到JavaScript:所有工作方式Apr 14, 2025 am 12:05 AM

从C/C 转向JavaScript需要适应动态类型、垃圾回收和异步编程等特点。1)C/C 是静态类型语言,需手动管理内存,而JavaScript是动态类型,垃圾回收自动处理。2)C/C 需编译成机器码,JavaScript则为解释型语言。3)JavaScript引入闭包、原型链和Promise等概念,增强了灵活性和异步编程能力。

JavaScript引擎:比较实施JavaScript引擎:比较实施Apr 13, 2025 am 12:05 AM

不同JavaScript引擎在解析和执行JavaScript代码时,效果会有所不同,因为每个引擎的实现原理和优化策略各有差异。1.词法分析:将源码转换为词法单元。2.语法分析:生成抽象语法树。3.优化和编译:通过JIT编译器生成机器码。4.执行:运行机器码。V8引擎通过即时编译和隐藏类优化,SpiderMonkey使用类型推断系统,导致在相同代码上的性能表现不同。

超越浏览器:现实世界中的JavaScript超越浏览器:现实世界中的JavaScriptApr 12, 2025 am 12:06 AM

JavaScript在现实世界中的应用包括服务器端编程、移动应用开发和物联网控制:1.通过Node.js实现服务器端编程,适用于高并发请求处理。2.通过ReactNative进行移动应用开发,支持跨平台部署。3.通过Johnny-Five库用于物联网设备控制,适用于硬件交互。

使用Next.js(后端集成)构建多租户SaaS应用程序使用Next.js(后端集成)构建多租户SaaS应用程序Apr 11, 2025 am 08:23 AM

我使用您的日常技术工具构建了功能性的多租户SaaS应用程序(一个Edtech应用程序),您可以做同样的事情。 首先,什么是多租户SaaS应用程序? 多租户SaaS应用程序可让您从唱歌中为多个客户提供服务

如何使用Next.js(前端集成)构建多租户SaaS应用程序如何使用Next.js(前端集成)构建多租户SaaS应用程序Apr 11, 2025 am 08:22 AM

本文展示了与许可证确保的后端的前端集成,并使用Next.js构建功能性Edtech SaaS应用程序。 前端获取用户权限以控制UI的可见性并确保API要求遵守角色库

JavaScript:探索网络语言的多功能性JavaScript:探索网络语言的多功能性Apr 11, 2025 am 12:01 AM

JavaScript是现代Web开发的核心语言,因其多样性和灵活性而广泛应用。1)前端开发:通过DOM操作和现代框架(如React、Vue.js、Angular)构建动态网页和单页面应用。2)服务器端开发:Node.js利用非阻塞I/O模型处理高并发和实时应用。3)移动和桌面应用开发:通过ReactNative和Electron实现跨平台开发,提高开发效率。

See all articles

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

AI Hentai Generator

AI Hentai Generator

免费生成ai无尽的。

热门文章

R.E.P.O.能量晶体解释及其做什么(黄色晶体)
4 周前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳图形设置
4 周前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您听不到任何人,如何修复音频
4 周前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.聊天命令以及如何使用它们
4 周前By尊渡假赌尊渡假赌尊渡假赌

热工具

ZendStudio 13.5.1 Mac

ZendStudio 13.5.1 Mac

功能强大的PHP集成开发环境

PhpStorm Mac 版本

PhpStorm Mac 版本

最新(2018.2.1 )专业的PHP集成开发工具

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

VSCode Windows 64位 下载

VSCode Windows 64位 下载

微软推出的免费、功能强大的一款IDE编辑器

Dreamweaver Mac版

Dreamweaver Mac版

视觉化网页开发工具