Rust是一门系统编程语言,专注于安全,尤其是并发安全,支持函数式和命令式以及泛型等编程范式的多范式语言。 Rust在语法上和C++类似,但是设计者想要在保证性能的同时提供更好的内存安全。 Rust最初是由Mozilla研究院的Graydon Hoare设计创造,然后在Dave Herman, Brendan Eich以及很多其他人的贡献下逐步完善的。 Rust的设计者们通过在研发Servo网站浏览器布局引擎过程中积累的经验优化了Rust语言和Rust编译器。 Rust编译器是在MIT License 和 Apache License 2.0双重协议声明下的免费开源软件。 Rust已经连续三年(2016,2017,2018)在Stack Overflow开发者调查的“最受喜爱编程语言”评选项目中折取桂冠。 from:https://baike.baidu.com/item/Rust%E8%AF%AD%E8%A8%80/9502634?fromtitle=Rust&fromid=12624017&fr=aladdin
View DetailsClustrixDB是一种集群式RDBMS,可确保事务处理符合ACID特性,同时可轻松的提供可扩展性和容错能力。 ClustrixDB集群由三个或更多节点(联网的同构服务器)组成。 ClustrixDB使用无共享架构。集群中的每个节点可以执行任何读取或写入操作。如果要扩充数据库容量,只需添加更多节点即可。 ClustrixDB的主要组件有助于实现性能和规模: 1)全局事务管理器(GTM),协调给定事务的处理。 2)Rebalancer,它在集群中自动分配数据。 3) Sierra数据库引擎,确定最佳查询执行计划,然后在分布式数据节点上执行该计划。 下图显示了ClustrixDB如何处理典型的查询。 全局事务管理器 通常通过横跨集群上分布式连接的负载均衡器,选择集群中的一个节点作为全局事务管理器(GTM)来开始处理ClustrixDB中的查询。然后在返回结果给调用者之前,GTM通过控制执行查询的每个一步、确认每一步成功完成、收集和确定执行结果等来全面管理事务。 ClustrixDB将查询编译为可执行查询片段,GTM将其分发到适当的节点以供执行。当中间结果可用时,它们将返回给GTM。一旦所有查询片段都已成功执行,GTM就完成结果并将它们返回给客户端,应用程序或用户。 Rebalancer 如果ClustrixDB的数据以前未在整个集群中分布,则不可能进行分布式处理。为了实现这一点,ClustrixDB使用了由其Rebalancer管理的专利数据分配方法。Rebalancer在集群中编排数据,以确保读取和写入始终平衡。它还保证在整个集群中维护数据的多个副本(副本)以确保容错。如果节点由于意外故障而丢失,则不会丢失任何数据。Rebalancer将自动确保创建和维护冗余副本。它还通过在添加新节点时将数据重新平衡到新节点并且在数据库保持在线的同时将数据从标记为要移除的节点移开而适应集群集大小的改变。 Rebalancer使用一致的散列算法将每个表行分配给该表的给定“切片”,并提供所有切片到每个节点的映射。这允许ClustrixDB快速轻松地确定相关数据的位置。Rebalancer在后台连续运行,不会影响正在进行的数据处理。 虽然数据被切片并分发到集群的许多节点,但是数据库表将始终作为应用程序的单个逻辑单元出现。Clustrix使用简单的SQL接口,并且不需要特殊的应用程序编程来访问分布在整个ClustrixDB集群中的数据。 如果ClustrixDB的数据以前未在整个集群中分布,则不可能进行分布式处理。为了实现这一点,ClustrixDB使用由其Rebalancer管理的专利数据分配方法。Rebalancer在集群中安排数据,以确保读取和写入始终平衡。它还保证在整个集群中维护数据的多个副本(副本)以确保容错。如果节点由于意外故障而丢失,则不会丢失任何数据。重新平衡器将自动确保创建和维护冗余副本。它还通过在添加新节点时将数据重新平衡到新节点并且在数据库保持在线的同时将数据从标记为要移除的节点移开而适应群集的改变大小。 Rebalancer使用一致的散列算法将每个表行分配给该表的给定“切片”,并提供所有切片到每个节点的映射。这允许ClustrixDB快速轻松地确定相关数据的位置。再平衡器在后台连续运行,不会影响正在进行的生产加工。 下面这张图片展示了Rebalancer如何横跨各个节点的的’切片’和表复制。请注意表的复制是如何分散在整个集群中的,以确保容错。在不同节点上的每个表切片至少是按时及复制的。 您可以看到在节点故障的情况下如何保护数据。如果节点故障,ClustrixDB将立即开始使用来自其他节点的故障节点数据的副本。然后Rebalancer立即开始通过将新副本复制到不同的节点上来重新定位该数据节点。 欲知详情请移步ClustrixDB’s Rebalancer。 Sierra数据库引擎 Sierra是处理查询计划和执行的ClustrixDB的SQL引擎。它专门设计用于在分布式、无共享(shared nothing)环境中工作,同时尽可能高效地访问分布式数据。Sierra数据库引擎由两部分组成: 1)Sierra Parallel Planner 确定SQL语句的最佳执行计划。 2)Sierra分布式执行引擎 根据计划执行查询片段,并提供中间结果。 Sierra Parallel Planner是一种基于成本的优化器,它使用概率统计,数据量,索引和查询运算符的开销来确定最有效的查询计划。 ClustrixDB Planner 的一个关键区别功能是它确定此计划,同时考虑数据在集群中的分布。 有关演示此查询分段如何工作的其他示例,请参阅ClustrixDB Sierra Database Engine. Sierra分布式执行引擎 一旦Sierra Planner确定了查询的最佳计划,它就被编译成机器可执行的查询片段。然后,这些编译的查询片段在集群中的不同节点上执行,提供了效率和增加的执行并发性。一旦每个节点上的执行完成,结果就返回到GTM节点,GTM节点然后组合部分结果并将最终结果集返回给用户。 ClustrixDB如何能够独特地利用其分布式执行以实现更快的结果的一个示例是分布式聚合处理。除了首先对每个节点的分布式数据上的数据计算部分聚合(SUM,MAX,MIN,AVG等)之外,计算类似于其它查询被分段和分布。中间结果然后由GTM合并以产生最终结果。 最后再让我们来看下在ClustrixDB中的分布查询。 结论 ClustrixDB使用自动数据分发,复杂的查询计划器和分布式执行模型,以在符合ACID的RDBMS中提供可扩展性和并发性。为了实现这一点,ClustrixDB使用了许多与其他大规模并行处理(MPP)数据库使用的相同的技术:它使用Paxos进行分布式事务解析,并使用多版本并发控制(MVCC)来防止事务冲突。借助上述主要组件,ClustrixDB为这种分布式执行提供了一个简单的SQL接口,同时还提供了可扩展性,效率和容错能力。 from:https://blog.csdn.net/luoduyu/article/details/53997249
View Detailspackage.josn
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
{ "name": "g-ex", "version": "1.0.0", "description": "a gulp template", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "keywords": [], "author": "", "license": "ISC", "devDependencies": { "autoprefixer": "^7.1.4", "babel-core": "^6.26.0", "babel-preset-env": "^1.6.0", "gulp": "^3.9.1", "gulp-babel": "^7.0.0", "gulp-clean-css": "^3.9.0", "gulp-concat": "^2.6.1", "gulp-connect": "^5.0.0", "gulp-less": "^3.3.2", "gulp-postcss": "^7.0.0", "gulp-rename": "^1.2.2", "gulp-sourcemaps": "^2.6.1", "gulp-uglify": "^3.0.0", "http-proxy-middleware": "^0.17.4", "uglify-es": "^3.1.3" }, "dependencies": { "gulp-file-include": "^1.2.0" } } |
gulpfile.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 |
var gulp = require('gulp'); var connect = require('gulp-connect'); var babel = require('gulp-babel'); var sourcemaps = require('gulp-sourcemaps'); var rename = require('gulp-rename'); var uglify = require('gulp-uglify'); var less = require('gulp-less'); var cleanCss = require('gulp-clean-css'); var autoprefixer = require('autoprefixer'); var postCss = require('gulp-postcss'); var proxy = require('http-proxy-middleware'); var fileinclude = require('gulp-file-include'); // 起服务 gulp.task('connect', function() { connect.server({ root: 'dist', livereload: true, port: 8888, middleware: function(connect, opt) { return [ // proxy('/printbox', { // target: 'http://172.20.8.30:8891', // changeOrigin:true // }), // proxy('/user', { // target: 'http://192.168.0.168:8099/user',//代理的目标地址 // changeOrigin:true,// // pathRewrite:{//路径重写规则 // '^/user':'' // } // }), ] } }); }); // html文件 gulp.task('html', function() { gulp.src('./*.html') .pipe(fileinclude({ prefix: '@@',//变量前缀 @@include basepath: './inc',//引用文件路径 indent:true//保留文件的缩进 })) .pipe(connect.reload()) .pipe(gulp.dest('./dist')); }); // css文件 gulp.task('less', ['html'], function() { gulp.src('./css/*.css') .pipe(connect.reload()) .pipe(gulp.dest('./dist/css')); gulp.src('./css/images/*.*') .pipe(connect.reload()) .pipe(gulp.dest('./dist/css/images')); }); // gulp.task('less', ['html'], function() { // gulp.src('./src/css/*.less') // .pipe(less()) // .pipe(postCss([autoprefixer({browsers: ['last 2 versions']})])) // .pipe(gulp.dest('./dist/css')) // .pipe(cleanCss()) // .pipe(rename({extname: '.min.css'})) // .pipe(connect.reload()) // .pipe(gulp.dest('./dist/css/min')) // }); // js文件 gulp.task('js', function() { gulp.src('./js/*.js') .pipe(connect.reload()) .pipe(gulp.dest('./dist/js')); }); // gulp.task('js',['html'] , function () { // gulp.src('./src/js/*.js') // .pipe(sourcemaps.init()) // .pipe(babel({ // presets: ['env'] // })) // .pipe(gulp.dest('./dist/js')) // .pipe(uglify()) // .pipe(rename({extname: '.min.js'})) // .pipe(sourcemaps.write()) // .pipe(connect.reload()) // .pipe(gulp.dest('./dist/js/min')) // }); // 图片 gulp.task('img', function () { gulp.src('./images/*.*') .pipe(connect.reload()) .pipe(gulp.dest('./dist/images')); gulp.src('./images/*.*') .pipe(connect.reload()) .pipe(gulp.dest('./dist/images/')); gulp.src('./images/banners/*.*') .pipe(connect.reload()) .pipe(gulp.dest('./dist/images/banners')); gulp.src('./images/blog-post/*.*') .pipe(connect.reload()) .pipe(gulp.dest('./dist/images/blog-post')); gulp.src('./images/payments/*.*') .pipe(connect.reload()) .pipe(gulp.dest('./dist/images/payments')); gulp.src('./images/products/*.*') .pipe(connect.reload()) .pipe(gulp.dest('./dist/images/products')); gulp.src('./images/sliders/*.*') .pipe(connect.reload()) .pipe(gulp.dest('./dist/images/sliders')); gulp.src('./images/testimonials/*.*') .pipe(connect.reload()) .pipe(gulp.dest('./dist/images/testimonials')); }); // fonts gulp.task('font', function(){ gulp.src('./fonts/*.*') .pipe(connect.reload()) .pipe(gulp.dest('./dist/fonts')); }); // 监控 gulp.task('watch', function() { gulp.watch(['./*.html','./inc/*.html'], ['html']); gulp.watch(['./js/*.js'], ['js']); gulp.watch(['./css/*.css'], ['less']); }); // 默认任务 gulp.task('default', ['connect', 'watch', 'js', 'less', 'img', 'font']); |
from:https://www.cnblogs.com/changzhenan/p/8329864.html
View DetailsSpring Boot 系列文章:http://www.ityouknow.com/spring-boot.html Spring Cloud 系列文章:http://www.ityouknow.com/spring-cloud.html Spring Cloud 从入门到精通:https://blog.csdn.net/valada/article/details/80892573
View DetailsSpring Cloud由众多子项目组成,如Spring Cloud Config、Spring Cloud Netflix、Spring Cloud Consul 等,提供了搭建分布式系统及微服务常用的工具,如配置管理、服务发现、断路器、智能路由、微代理、控制总线、一次性token、全局锁、选主、分布式会话和集群状态等,满足了构建微服务所需的所有解决方案。 服务发现——Netflix Eureka 客服端负载均衡——Netflix Ribbon 断路器——Netflix Hystrix 服务网关——Netflix Zuul 分布式配置——Spring Cloud Config Eureka 2eur.png 一个RESTful服务,用来定位运行在AWS地区(Region)中的中间层服务。由两个组件组成:Eureka服务器和Eureka客户端。Eureka服务器用作服务注册服务器。Eureka客户端是一个java客户端,用来简化与服务器的交互、作为轮询负载均衡器,并提供服务的故障切换支持。Netflix在其生产环境中使用的是另外的客户端,它提供基于流量、资源利用率以及出错状态的加权负载均衡。 Ribbon Ribbon,主要提供客户侧的软件负载均衡算法。 3ri.png Ribbon客户端组件提供一系列完善的配置选项,比如连接超时、重试、重试算法等。Ribbon内置可插拔、可定制的负载均衡组件。下面是用到的一些负载均衡策略: 简单轮询负载均衡 加权响应时间负载均衡 区域感知轮询负载均衡 随机负载均衡 Ribbon中还包括以下功能: 易于与服务发现组件(比如Netflix的Eureka)集成 使用Archaius完成运行时配置 使用JMX暴露运维指标,使用Servo发布 多种可插拔的序列化选择 异步和批处理操作(即将推出) 自动SLA框架(即将推出) 系统管理/指标控制台(即将推出) Hystrix 41h.png 断路器可以防止一个应用程序多次试图执行一个操作,即很可能失败,允许它继续而不等待故障恢复或者浪费 CPU 周期,而它确定该故障是持久的。断路器模式也使应用程序能够检测故障是否已经解决。如果问题似乎已经得到纠正,应用程序可以尝试调用操作。欢迎大家一起学习研究相关技术愿意了解源码的朋友直接求求交流分享技术:2147775633 42h.png 断路器增加了稳定性和灵活性,以一个系统,提供稳定性,而系统从故障中恢复,并尽量减少此故障的对性能的影响。它可以帮助快速地拒绝对一个操作,即很可能失败,而不是等待操作超时(或者不返回)的请求,以保持系统的响应时间。如果断路器提高每次改变状态的时间的事件,该信息可以被用来监测由断路器保护系统的部件的健康状况,或以提醒管理员当断路器跳闸,以在打开状态。 43h.png 流程图 44h.png Zuul 51z.png 类似nginx,反向代理的功能,不过netflix自己增加了一些配合其他组件的特性。 Spring Cloud Config 52z.png 这个还是静态的,得配合Spring Cloud Bus实现动态的配置更新。 更多详细源码参考来源:http://minglisoft.cn/honghu/technology.html 作者:IT小跑兵 链接:https://www.jianshu.com/p/02f3995001d0 来源:简书 简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。
View Details引言 在使用asp.net core 进行api开发完成后,书写api说明文档对于程序员来说想必是件很痛苦的事情吧,但文档又必须写,而且文档的格式如果没有具体要求的话,最终完成的文档则完全取决于开发者的心情。或者详细点,或者简单点。那么有没有一种快速有效的方法来构建api说明文档呢?答案是肯定的, Swagger就是最受欢迎的REST APIs文档生成工具之一! 为什么使用Swagger作为REST APIs文档生成工具 Swagger 可以生成一个具有互动性的API控制台,开发者可以用来快速学习和尝试API。 Swagger 可以生成客户端SDK代码用于各种不同的平台上的实现。 Swagger 文件可以在许多不同的平台上从代码注释中自动生成。 Swagger 有一个强大的社区,里面有许多强悍的贡献者。 asp.net core中如何使用Swagger生成api说明文档呢 Swashbuckle.AspNetCore 是一个开源项目,用于生成 ASP.NET Core Web API 的 Swagger 文档。 NSwag 是另一个用于将 Swagger UI 或 ReDoc 集成到 ASP.NET Core Web API 中的开源项目。 它提供了为 API 生成 C# 和 TypeScript 客户端代码的方法。 下面以Swashbuckle.AspNetCore为例为大家进行展示 Swashbuckle由哪些组成部分呢? Swashbuckle.AspNetCore.Swagger:将 SwaggerDocument 对象公开为 JSON 终结点的 Swagger 对象模型和中间件。 Swashbuckle.AspNetCore.SwaggerGen:从路由、控制器和模型直接生成 SwaggerDocument 对象的 Swagger 生成器。 它通常与 Swagger 终结点中间件结合,以自动公开 Swagger JSON。 Swashbuckle.AspNetCore.SwaggerUI:Swagger UI 工具的嵌入式版本。 它解释 Swagger JSON 以构建描述 Web API 功能的可自定义的丰富体验。 它包括针对公共方法的内置测试工具。 如何使用vs2017安装Swashbuckle呢? 从“程序包管理器控制台”窗口进行安装 转到“视图” > “其他窗口” > “程序包管理器控制台” 导航到包含 TodoApi.csproj 文件的目录 请执行以下命令 ·Install-Package […]
View Details1 HSqlDB简介 HSQLDB是一款Java内置的数据库,非常适合在用于快速的测试和演示的Java程序中。(无需独立安装数据库) HSQLDB有三种模式: 1. Server 就像Mysql那样 2. In-Process 又叫做 Standalone 模式,数据放在本地文件,伴随JVM一起启动,是HSQLDB的主要应用场景 3. Memory-only, 仅仅在内存中,一旦重启,数据就消失。 2 客户端 2.1 运行HSQLDB_Client类中的main方法 其主方法调用了DatabaseManagerSwing的主方法 这回导致启动一个Swing做的客户端 2.2 创建数据库,账号和密码 填写连接参数 1. Setting Name:输入test 2. Type: 选择HSQL Database Engine Standalone 3. Driver: 使用默认的org.hsqldb.jdbcDriver 4. URL: 输入 Jdbc:hsqldb:file: D:/SoftWareInstall/HSqlDB/test 5. User: root 6: Password:root 第3步: 这是Standalone方式,对于同一个数据库,只能启动一次,不支持多进程连接同一个数据库,所以后续在写JAVA代码连接的时候,必须把这个客户端关闭掉才行。 第4步: Jdbc:hsqldb:file: D:/SoftWareInstall/HSqlDB/test会导致在D:/SoftWareInstall/HSqlDB目录下创建一个test数据库 第5,6步:会导致创建账号密码,以后再连接D:/SoftWareInstall/HSqlDB下的test数据库,就必须用这个账号密码了。 2.3 创建表 CREATE TABLE category ( id int NOT NULL GENERATED BY DEFAULT AS IDENTITY, name varchar(255) DEFAULT NULL, PRIMARY KEY (id) ) ; insert into category values (null,'水果'); insert into category values (null,'衣服'); insert into […]
View Details闭包 既保证了 内部函数的私有性 又可以向外公开 通过一个已有对象 向它注入属性
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
/** * 闭包 * 在函数中定义的函数,在外部使用 * 1、在函数内部定义的函数,在外部不能访问 */ function a(){ /** * b函数是一个私有函数 */ function b(){ alert("aaaa"); } return b; } //var bb = a(); //bb(); (function(){ var aa = 5; function a(){ /** * 公开api */ return { b:b, c:c } } function b(){ alert("b"); } function c(){ alert("c"); } window.a = a; })(); var json = window.a(); json.b(); json.c(); |
from:https://www.cnblogs.com/friends-wf/p/3781859.html
View Details
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
/** * 防御型分号 */ ; (function () { //code.... console.log('一开始,我自己执行了!!!'); })(); /** * 形参 -> 实参 * 定义形参->接收实参->最后打印. */ (function (a, b, c) { console.log(a + b + c); })(1, 2, 3) // (function(i){ // console.log(i); // })(window); /** * 声明了不需要返回函数(return) */ void function () { // code.... console.log('不需要返回return!'); }(); |
from:https://www.cnblogs.com/cisum/p/9577246.html
View Details一、什么是闭包和闭包的几种写法和用法 1、什么是闭包 闭包,官方对闭包的解释是:一个拥有许多变量和绑定了这些变量的环境的表达式(通常是一个函数),因而这些变量也是该表达式的一部分。闭包的特点: 1. 作为一个函数变量的一个引用,当函数返回时,其处于激活状态。 2. 一个闭包就是当一个函数返回时,一个没有释放资源的栈区。 简单的说,Javascript允许使用内部函数—即函数定义和函数表达式位于另一个函数的函数体内。而且,这些内部函数可以访问它们所在的外部函数中声明的所有局部变量、参数和声明的其他内部函数。当其中一个这样的内部函数在包含它们的外部函数之外被调用时,就会形成闭包。 2、闭包的几种写法和用法 首先要明白,在JS中一切都是对象,函数是对象的一种。下面先来看一下闭包的5种写法,简单理解一下什么是闭包。后面会具体解释。
1 2 3 4 5 6 7 8 9 10 11 |
//第1种写法 function Circle(r) { this.r = r; } Circle.PI = 3.14159; Circle.prototype.area = function() { return Circle.PI * this.r * this.r; } var c = new Circle(1.0); alert(c.area()); |
这种写法没什么特别的,只是给函数添加一些属性。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
//第2种写法 var Circle = function() { var obj = new Object(); obj.PI = 3.14159; obj.area = function( r ) { return this.PI * r * r; } return obj; } var c = new Circle(); alert( c.area( 1.0 ) ); |
这种写法是声明一个变量,将一个函数当作值赋给变量。
1 2 3 4 5 6 7 8 |
//第3种写法 var Circle = new Object(); Circle.PI = 3.14159; Circle.Area = function( r ) { return this.PI * r * r; } alert( Circle.Area( 1.0 ) ); |
这种方法最好理解,就是new 一个对象,然后给对象添加属性和方法。
1 2 3 4 5 6 7 8 |
//第4种写法 var Circle={ "PI":3.14159, "area":function(r){ return this.PI * r * r; } }; alert( Circle.area(1.0) ); |
这种方法使用较多,也最为方便。var obj = {}就是声明一个空的对象。
1 2 3 4 |
//第5种写法 var Circle = new Function("this.PI = 3.14159;this.area = function( r ) {return r*r*this.PI;}"); alert( (new Circle()).area(1.0) ); |
说实话,这种写法我是没用过,大家可以参考一下。 总的来说,上面几种方法,第2中和第4中较为常见,大家可以根据习惯选择。 上面代码中出现了JS中常用的Prototype,那么Prototype有什么用呢?下面我们来看一下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
var dom = function(){ }; dom.Show = function(){ alert("Show Message"); }; dom.prototype.Display = function(){ alert("Property Message"); }; dom.Display(); //error dom.Show(); var d = new dom(); d.Display(); d.Show(); //error |
我们首先声明一个变量,将一个函数赋给他,因为在Javascript中每个函数都有一个Portotype属性,而对象没有。添加两个方法,分别直接添加和添加打破Prototype上面,来看下调用情况。分析结果如下: 1、不使用prototype属性定义的对象方法,是静态方法,只能直接用类名进行调用!另外,此静态方法中无法使用this变量来调用对象其他的属性! 2、使用prototype属性定义的对象方法,是非静态方法,只有在实例化后才能使用!其方法内部可以this来引用对象自身中的其他属性! 下面我们再来看一段代码:
1 2 3 4 5 6 7 8 9 10 |
var dom = function(){ var Name = "Default"; this.Sex = "Boy"; this.success = function(){ alert("Success"); }; }; alert(dom.Name); alert(dom.Sex); |
大家先看看,会显示什么呢? 答案是两个都显示Undefined,为什么呢?这是由于在Javascript中每个function都会形成一个作用域,而这些变量声明在函数中,所以就处于这个函数的作用域中,外部是无法访问的。要想访问变量,就必须new一个实例出来。
1 2 3 4 5 6 7 8 9 |
var html = { Name:'Object', Success:function(){ this.Say = function(){ alert("Hello,world"); }; alert("Obj Success"); } }; |
再来看看这种写法,其实这是Javascript的一个"语法糖",这种写法相当于:
1 2 3 4 5 6 7 |
var html = new Object(); html.Name = 'Object'; html.Success = function(){ this.Say = function(){ alert("Hello,world"); }; alert("Obj Success"); |
变量html是一个对象,不是函数,所以没有Prototype属性,其方法也都是公有方法,html不能被实例化。否则会出现如下错误: 但是他可以作为值赋给其它变量,如var o = html; 我们可以这样使用它:
1 2 |
alert(html.Name); html.Success(); |
说到这里,完了吗?细心的人会问,怎么访问Success方法中的Say方法呢?是html.Success.Say()吗? 当然不是,上面刚说过由于作用域的限制,是访问不到的。所以要用下面的方法访问:
1 2 3 4 5 6 7 8 9 |
var s = new html.Success(); s.Say(); //还可以写到外面 html.Success.prototype.Show = function(){ alert("HaHa"); }; var s = new html.Success(); s.Show(); |
关于Javascript作用域的问题,不是一两句能说清楚的,有兴趣的大家可以网上找些资料看看。 二、Javascript闭包的用途 事实上,通过使用闭包,我们可以做很多事情。比如模拟面向对象的代码风格;更优雅,更简洁的表达出代码;在某些方面提升代码的执行效率。 1、匿名自执行函数 我们知道所有的变量,如果不加上var关键字,则默认的会添加到全局对象的属性上去,这样的临时变量加入全局对象有很多坏处, 比如:别的函数可能误用这些变量;造成全局对象过于庞大,影响访问速度(因为变量的取值是需要从原型链上遍历的)。 除了每次使用变量都是用var关键字外,我们在实际情况下经常遇到这样一种情况,即有的函数只需要执行一次,其内部变量无需维护, 比如UI的初始化,那么我们可以使用闭包:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
var data= { table : [], tree : {} }; (function(dm){ for(var i = 0; i < dm.table.rows; i++){ var row = dm.table.rows[i]; for(var j = 0; j < row.cells; i++){ drawCell(i, j); } } })(data); |
我们创建了一个匿名的函数,并立即执行它,由于外部无法引用它内部的变量,因此在函数执行完后会立刻释放资源,关键是不污染全局对象。 2、结果缓存 我们开发中会碰到很多情况,设想我们有一个处理过程很耗时的函数对象,每次调用都会花费很长时间, 那么我们就需要将计算出来的值存储起来,当调用这个函数的时候,首先在缓存中查找,如果找不到,则进行计算,然后更新缓存并返回值,如果找到了,直接返回查找到的值即可。闭包正是可以做到这一点,因为它不会释放外部的引用,从而函数内部的值可以得以保留。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
var CachedSearchBox = (function(){ var cache = {}, count = []; return { attachSearchBox : function(dsid){ if(dsid in cache){//如果结果在缓存中 return cache[dsid];//直接返回缓存中的对象 } var fsb = new uikit.webctrl.SearchBox(dsid);//新建 cache[dsid] = fsb;//更新缓存 if(count.length > 100){//保正缓存的大小<=100 delete cache[count.shift()]; } return fsb; }, clearSearchBox : function(dsid){ if(dsid in cache){ cache[dsid].clearSelection(); } } }; })(); CachedSearchBox.attachSearchBox("input"); |
这样我们在第二次调用的时候,就会从缓存中读取到该对象。 3、封装
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
var person = function(){ //变量作用域为函数内部,外部无法访问 var name = "default"; return { getName : function(){ return name; }, setName : function(newName){ name = newName; } } }(); print(person.name);//直接访问,结果为undefined print(person.getName()); person.setName("abruzzi"); print(person.getName()); 得到结果如下: undefined default abruzzi |
4、实现类和继承
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
function Person(){ var name = "default"; return { getName : function(){ return name; }, setName : function(newName){ name = newName; } } }; var p = new Person(); p.setName("Tom"); alert(p.getName()); var Jack = function(){}; //继承自Person Jack.prototype = new Person(); //添加私有方法 Jack.prototype.Say = function(){ alert("Hello,my name is Jack"); }; var j = new Jack(); j.setName("Jack"); j.Say(); alert(j.getName()); |
我们定义了Person,它就像一个类,我们new一个Person对象,访问它的方法。 下面我们定义了Jack,继承Person,并添加自己的方法。 from:https://www.cnblogs.com/jiayc/p/9365837.html
View Details