如何在按照自己义愿js中显示*有规律的图案

在 SegmentFault,学习技能、解决问题
每个月,我们帮助 1000 万的开发者解决各种各样的技术问题。并助力他们在技术能力、职业生涯、影响力上获得提升。
问题对人有帮助,内容完整,我也想知道答案
问题没有实际价值,缺少关键内容,没有改进余地
看到前同事的一段代码:
var st = $("#idA");
$("#idB").val() == "1" ? st.removeClass("hide") : [st.addClass("hide")][st.val("")];
虽然我也喜欢用js三元运算式,但后面这个用中括号括起来的语法还是第一次见,网上查了很久,最接近的答案也不过是在里说到“JavaScript中括号有四种语义”:
语义1,声明数组语义2,取数组成员语义3,定义对象成员(可以不遵循标识符规则)语义4,取对象成员
但我却依然很困惑:按照这四个语义解释,也就是中括号里面的都是数组或对象,但我上面的代码里,中括号里的明明是语句呀。求高手指导!
答案对人有帮助,有参考价值
答案没帮助,是错误的答案,答非所问
这段代码很糟糕,一定要避免这样写。
但是,并没有任何神奇的。
[st.addClass("hide")][st.val("")];
这一条语句,等价于下面两条语句
st.addClass("hide");
st.val("");
他用这种少见的方式强行把两个表达式合并成一个表达式,为的就是能够塞进三元运算符的第三个操作数位置。
正如@kikong说的,用逗号表达式也一样。
至于你问有什么语法意义:
[expression1][expression2]
第一个中括号是“Array Initialiser”,说白了就是数组字面量,用来定义一个数组。第二个中括号是“Property Accessor”,也就是用来访问对象的属性(包括数组的元素)。
以上两种情况下,都会首先计算中括号中的表达式的值。你的代码并不是为了得到一个值,而是利用了求值过程中产生的副作用。
所以,这段代码逻辑上没有问题,但千万不可模仿。
分享到微博?
关闭理由:
删除理由:
忽略理由:
推广(招聘、广告、SEO 等)方面的内容
与已有问题重复(请编辑该提问指向已有相同问题)
答非所问,不符合答题要求
宜作评论而非答案
带有人身攻击、辱骂、仇恨等违反条款的内容
无法获得确切结果的问题
非开发直接相关的问题
非技术提问的讨论型问题
其他原因(请补充说明)
我要该,理由是:
在 SegmentFault,学习技能、解决问题
每个月,我们帮助 1000 万的开发者解决各种各样的技术问题。并助力他们在技术能力、职业生涯、影响力上获得提升。jQuery和AngularJS的区别浅析
转载 &更新时间:日 08:59:39 & 投稿:junjie
这篇文章主要介绍了jQuery和AngularJS的区别浅析,本文着重讲解一个熟悉jQuery开的程序员如何应对AngularJS中的一些编程思想的转变,需要的朋友可以参考下
最近一直在研究angularjs,最大的感受就是它和之前的jQuery以及基于jQuery的各种库设计理念完全不同,如果不能认识到这点而对于之前做jQuery开发的程序员,去直接学习angularjs的话,很可能学了很久还不知道这个东西能用来干什么以及怎么使用,怎么和UI进行结合等问题,在stackoverflow上找到一篇关于这方面的文章,阅读之后颇有收获,在此基础上将它译成中文,以求抛砖引玉大家一同学习。
原问题:假如我熟悉利用jQuery去开发客户端应用,那么我怎么上手angularjs,能否描述下所需要的模式转变,下面这些问题能够帮助你给出一个回答:
1.在设计客户端web应用的时候有什么区别,最大的区别是什么?
2.我应该停止使用哪些技术,同时又使用哪些技术作为替代?
3.是否存在服务端需要考虑的东西或者说一些限制呢?
1.不要首先设计好你的页面,然后再通过DOM操作去修改它
在jQuery中,你首先设计了一个page,然后再去动态修改它的内容,这是因为jQuery被设计用来进行扩展并在这个前提下大幅度地增加和修改内容,但是在angularjs中,你必须在心中先设计好你的架构,
从一开始,你就要摒弃“我拥有一个DOM元素并且想让它去做某件事”,代之为“我需要完成什么任务,然后接着设计你的应用,最后再去设计你的视图view层”。
2.不要使用angularjs去扩展jQuery
相应地,不要存在说让jQuery去干某些事情,然后在此基础上添加angularjs的功能让它去管理model以及controller的想法。所以我一般不推荐AngularJS开发新手同时使用jQuery,至少在他们还没有适应AngularJS的开发模式之前不会去推荐这样做,但是当你真正开始适应angularjs 的方式之后,你会发觉这是一件很诱人的事情。
我曾经看到过很多开发者采用将150到200行代码的jQuery插件利用angularjs的回调以及$apply方法封装起来,这种方式使得代码看起来极其复杂,但是实际上他们让这些插件跑起来了!问题在于,在大部分情况下jQuery插件能够用angularjs进行重写,并且可能只会使用很少量的代码,同时这种重写使得代码很直观且易于理解,这显然好过于将jQuery代码直接做封装。
所以最后说,当你遇见问题的时候,首先要以angularjs的思维进行思考,如果找不到解决方案,可以求助于社区,如果说没有人能够给出一个简单的方案,那么才考虑使用jQuery,不要让jQuery成为你的拐杖,否则你永远掌握不了AngularJS。
3.要以架构为中心进行思考
首先你要知道单页应用属于web应用,它们不是传统的多网页网站,所以我们要同时作为一个服务端和客户端开发者的思维进行思考,我们需要思考如何将我们的应用分为独立的,可扩展的以及可测试的部分。
那么接下来我们如何采用AngularJS思维去工作呢,以下是一些将其与jQuery对比之后的基本准则:
以下是某个应用的视图层:
在jQuery中,我们动态地去修改这个视图,我们使用ul去定义一个dropdown menu
&ul class="main-menu"&
&&& &li class="active"&
&&&&&&& &a href="#/home"&Home&/a&
&&&&&&& &a href="#/menu1"&Menu 1&/a&
&&&&&&& &ul&
&&&&&&&&&&& &li&&a href="#/sm1"&Submenu 1&/a&&/li&
&&&&&&&&&&& &li&&a href="#/sm2"&Submenu 2&/a&&/li&
&&&&&&&&&&& &li&&a href="#/sm3"&Submenu 3&/a&&/li&
&&&&&&& &/ul&
&&&&&&& &a href="#/home"&Menu 2&/a&
在jQuery中,我们采用如下逻辑使用这个dropdownMenu
$('.main-menu').dropdownMenu();
让我们回头看看这个view,你会发现它的功能并不是很直白,对于小型应用来讲,这样是可以的,但是对于大型应用来讲,这种方式会让人费解并且难以维护;
在angularjs中,这个视图实际上是一项基于视图的功能,我们可以这样来定义ul
&ul class="main-menu" dropdown-menu&
这两种方式实际上做了同样的事情,但是在AngularJS方式下任何人看到这个视图模板就知道接下来要干什么。无论何时当一个新成员加入开发团队之后他都能够看到这里并发现这里有一个叫做dropdownMenu的指令去操作view,他不需要去猜想正确的答案或者审查其他的代码,这个视图就直接告诉我们它要做什么,相比于jQuery,它更为简洁。
常常有些AngularJS新手问这样的问题:我怎么才能找到某个确切类型的所有link并在此基础上添加一个directive,但是当我们回答了“你不应该这样去做,你这是一种半jQuery半angularjs的想法”时,他们会觉得很吃惊。
问题在于他们试图在AngularJS背景下用jQuery去做某件事,这通常不是一种好的方式,在指令之外你不需要去做任何dom操作,而指令是直接内添加在视图上的,所以意图已经很明显了。记住,不要先设计好之后再去修改,而是先有架构然后在这个框架下再去设计。
这是到目前为止AngularJS最令人瞩目的特性了,在数据绑定方面它舍弃了对DOM的操作方式,而这一切都是由AngularJS来自动更新视图,你不必写操作dom的代码,在jQuery中,我们常常按照以下方式响应事件并修改视图:
& url: '/myEndpoint.json',
& success: function ( data, status ) {
&&& $('ul#log').append('&li&Data Received!&/li&');
相对于这样一个视图
&ul class="messages" id="log"&
除了混杂的问题之外,我们还存在我之前提到的如何表明自己意图的问题。但是更为重要的是,我们必须人工手动去引用并更新这个DOM节点,如果我们想删除其中一条,那么必须以编程方式去操作那个DOM元素,那么在这种情况下我们怎么去测试DOM节点之外的逻辑呢,亦或者我们想改变展示方式呢?
以上代码显得凌乱又脆弱,但是在AngularJS中,我们可以这样做:
$http( '/myEndpoint.json' ).then( function ( response ) {
&&& $scope.log.push( { msg: 'Data Received!' } );
我们的视图应该像下面这样
&ul class="messages"&
&&& &li ng-repeat="entry in log"&{{ entry.msg }}&/li&
在那种情况下,我们的视图也可以这样
&div class="messages"&
&&& &div class="alert" ng-repeat="entry in log"&
&&&&&&& {{ entry.msg }}
&&& &/div&
现在我们不使用ul,而是使用Bootstrap的弹出框,但是我们不用修改controller中的代码,更为重要的是,不管是数据如何修改,视图层也会自动随之发生变化,非常简洁!
尽管我这里不会做演示,但是你需要知道数据绑定是双向的,你可以编辑数据通过添加指令&input ng-model="entry.msg" /&,此外还有很多其他的令人兴奋的地方。
区别model层
在jQuery中,DOM类似于一种model,但是在AngularJS中,我们拥有不同于jQuery中的model层以便我们可以以任何我们想要的方式去管理它,它是完全独立于视图之外的。这种方式是有助于我们进行数据绑定并且可以保持对分离的关注,而且可以具备更好的可测试性。
关注点分离
以上所讲都和这个总体的话题相关:让你关注分离,你的视图层显示记录,你的model层代表数据,你还有个服务层用来执行这些可复用的任务。你使用directive来执行dom操作并扩展你的视图,并将它和controller连接起来,这也就是我在其他方面提到的有关于增强可测试性的原因。
帮助我们解决关注点分离的是依赖注入(DI),如果你是一个服务端开发者(Java或者PHP),你可能已经很熟悉这个概念了,但是如果你是从事客户端开发的,你会觉得这个概念可能有些多余和纯属追求时髦,但是实际上不是这样。
从广义的角度讲,DI意味着你可以自由地声明组件然后从这些组件中进行实例化,这是理所当然的。你不必知道加载顺序,文件位置等诸如此类的事情,这种魔力不是能够立即看到,但是我会给出一个例子:测试。
我们说在应用中,我们需要一个依赖于应用状态和本地存储的服务用来通过一个rest API来执行服务端存储,当我们测试我们的controller时,我们不必和服务端进行通信,毕竟只是在测试controller而已。我们仅添加一个与我们最初组件相同的mock服务,注入器能够确保我们的controller获得一个虚拟的服务,controller自身不必也不需要了解这种差异。
那么说说测试吧。
4.以测试驱动的开发
这部分是一个架构的第三部分,但是他是很重要的,以至于我需要将它放在最重要的位置。
在我们所有见过的,用过的以及写过的jQuery插件中,有多少具有一套测试组件呢?其实并不多,这是因为jQuery在测试上不易控制,但是AngularJS却与此不同。
在jQuery中,测试的唯一方法是使用一个demo页去创建一个独立组件来使得我们的测试可以执行dom操作。我们接下来我们必须开发一个独立的组件然后将它集成到我们的应用中来,这是多不方便啊!在很多情况下,当我们使用jQuery开发实际上是做了很多重复开发而不是以测试驱动的开发,这又能怪我们吗?
但是在AngularJS中我们可以关注分离点,所以我们可以做一些测试驱动的开发。例如,我们有一个directive用来说明在menu中我们的当前路径,我们可以在视图中这样声明:
&a href="/hello" when-active&Hello&/a&
好了,现在我们可以写一个测试用来测试这个不存在的指令when-active了
it( 'should add "active" when the route changes', inject(function() {
&&& var elm = $compile( '&a href="/hello" when-active&Hello&/a&' )( $scope );
&&& $location.path('/not-matching');
&&& expect( elm.hasClass('active') ).toBeFalsey();
&&& $location.path( '/hello' );
&&& expect( elm.hasClass('active') ).toBeTruthy();
我们直接run测试用例,你会发现是失败的,这时候需要创建这个指令,如下:
.directive( 'whenActive', function ( $location ) {
&&& return {
&&&&&&& scope: true,
&&&&&&& link: function ( scope, element, attrs ) {
&&&&&&&&&&& scope.$on( '$routeChangeSuccess', function () {
&&&&&&&&&&&&&&& if ( $location.path() == element.attr( 'href' ) ) {
&&&&&&&&&&&&&&&&&&& element.addClass( 'active' );
&&&&&&&&&&&&&&& }
&&&&&&&&&&&&&&& else {
&&&&&&&&&&&&&&&&&&& element.removeClass( 'active' );
&&&&&&&&&&&&&&& }
&&&&&&&&&&& });
再次run这个测试用例,你会发现通过了并且菜单如请求的样子显示,我们的开发是兼有反复性和可测试性,非常酷吧!
5.从概念上讲,指令不是打包的jQuery
你常常听说,dom操作只能在指令中,这是必须的,你必须严肃对待。
让我们深入讨论,
某些指令仅仅是装饰我们的视图(例如ngClass),因此有时候直接操作dom是可以的,但是当一个指令类似于一个小物件并且拥有自己的模板,那么它应该当做一个分离的关注点,这就是说,它的模板需要和link中的执行逻辑以及其他controller函数分离开。
AngularJS拥有一整套的工具可以是这种分离更简单,使用ngClass指令,我们可以动态地更新class,使用ngBind我们可以进行双向数据绑定,使用ngShow和ngHide 我们
可以采用编程的形式显示和隐藏一个元素,也包括我们自己写的很多指令。换句话说,我们可以不用Dom操作而完成所有工作,dom操作越少,指令越容易测试,越容易指定他们的style属性,就越容易在将来改变他们,那么他们就越容易复用和分发。
我看过很多AngularJS新手使用指令封装一大串 jQuery代码,换句话说,既然我不能在controller里面进行dom操作,那么我可以将他放在指令中,虽然这相对于直接操作dom好很多,但是任然是错误的。
看看我们在上面的记录,即使我们将其放在一个指令中,我们任然需要以Angular的方式去操作它,这种方式不执行dom操作!在很多时候dom操作是需要的,但是这种情况比你想的要少得多。当我们需要做dom操作的时候先问问自己这里是否必须这样做,这才是一种更好的方式。
下面是一个简单的例子用来表明我常常见到的一种模式,我们需要I一个可切换的button:
.directive( 'myDirective', function () {
&&& return {
&&&&&&& template: '&a class="btn"&Toggle me!&/a&',
&&&&&&& link: function ( scope, element, attrs ) {
&&&&&&&&&&& var on =
&&&&&&&&&&& $(element).click( function () {
&&&&&&&&&&&&&&& on = !
&&&&&&&&&&&&&&& $(element).toggleClass('active', on);
&&&&&&&&&&& });
在以上例子中存在以下错误:
1.首先,jQuery是不必要的,这里的工作完全不需要jQuery!
2.第二,即使我们已经在页面中引入了jquery,但是我们没有理由去使用它,我们可以使用angular.element而我们的组件也能够运行,即使这个项目中没有引入jQuery。
3.第三,假设jquery是需要的在我们的指令中,我们可以使用jqLite去进行替代,只要引入jQuery即可,所以我们不必使用$而是使用angular.
4.第四,和第三点联系很紧密,jqLite元素不必使用$包裹起来,element元素传递到link函数中已经是一个jQuery对象了;
5.第五,我们之前已经说过,为什么不将我们的模板和逻辑混合起来呢?
以上指令可以按照如下方式来重写,即使在最复杂的情况下看起来也如此简单。
.directive( 'myDirective', function () {
&&& return {
&&&&&&& scope: true,
&&&&&&& template: '&a class="btn" ng-class="{active: on}" ng-click="toggle()"&Toggle me!&/a&',
&&&&&&& link: function ( scope, element, attrs ) {
&&&&&&&&&&& scope.on =
&&&&&&&&&&& scope.toggle = function () {
&&&&&&&&&&&&&&& scope.on = !scope.
&&&&&&&&&&& };
模板元素是在 template属性中,你可以很容易替换掉它的style,而逻辑根本不用发生变化,达到了完全复用!
还有其他的好处,比如测试起来很简单,不管模板里面是什么,指令API都不会发生改变,所以重构它很简单。你可以随意多次改变你的模板而不用改变指令,无论你怎么改变,你的测试总能通过!
所以说指令不是一堆jQuery代码的集合,比如函数等,而是HTML代码的扩展,如果HTML代码不能实现你需要的功能,你可以写一个指令去实现它,然后像使用HTML那样去使用它。
以另外一种方式讲,AngularJS如果不做额外的事情,想想我们怎么能够使用ngClick,ngClass指令呢?
不要总使用jquery ,甚至不要去引用它,它会阻止你前进,当我们回到这个问题—你知道你怎么在AngularJS中以jquery方式解决问题,但是当你使用诸如$等选择器时,你要想想它们实际上是禁锢了AngularJS,如果你不知道怎么不用jQuery实现,那么去请教别人,一次一次去问,最好的方式是不需要使用jQuery,使用jQuery只会导致你的工作量提升。
您可能感兴趣的文章:
大家感兴趣的内容
12345678910
最近更新的内容
常用在线小工具js中(function(){xxx})();写法解析
自执行匿名函数:
常见格式:(function() { /* code */ })();解释:包围函数(function(){})的第一对括号向脚本返回未命名的函数,随后一对空括号立即执行返回的未命名函数,括号内为匿名函数的参数。作用:可以用它创建命名空间,只要把自己所有的代码都写在这个特殊的函数包装内,那么外部就不能访问,除非你允许(变量前加上window,这样该函数或变量就成为全局)。各JavaScript库的代码也基本是这种组织形式。
总结一下,执行函数的作用主要为 匿名 和 自动执行,代码在被解释时就已经在运行了。
(function () {
!function () {
~function () {
-function () {
+function () {
function与感叹号
最近有空可以让我静下心来看看各种代码,function与感叹号的频繁出现,让我回想起2个月前我回杭州最后参加团队会议的时候,抛出的一样的问题:如果在function之前加上感叹号
(!) 会怎么样?比如下面的代码:
!function(){alert('iifksp')}()
在控制台运行后得到的值时true,为什么是true这很容易理解,因为这个匿名函数没有返回值,默认返回的就是undefined,求反的结果很自然的就是true。所以问题并不在于结果值,而是在于,为什么求反操作能够让一个匿名函数的自调变的合法?
平时我们可能对添加括号来调用匿名函数的方式更为习惯:
(function(){alert('iifksp')})()
(function(){alert('iifksp')}())
虽然上述两者括号的位置不同,不过效果完全一样。
那么,是什么好处使得为数不少的人对这种叹号的方式情有独钟?如果只是为了节约一个字符未免太没有必要了,这样算来即使一个100K的库恐怕也节省不了多少空间。既然不是空间,那么就是说也许还有时间上的考量,事实很难说清,文章的最后有提到性能。
回到核心问题,为什么能这么做?甚至更为核心的问题是,为什么必须这么做?
其实无论是括号,还是感叹号,让整个语句合法做的事情只有一件,就是让一个函数声明语句变成了一个表达式。
function a(){alert('iifksp')}
这是一个函数声明,如果在这么一个声明后直接加上括号调用,解析器自然不会理解而报错:
function a(){alert('iifksp')}()
因为这样的代码混淆了函数声明和函数调用,以这种方式声明的函数 a,就应该以 a(); 的方式调用。
但是括号则不同,它将一个函数声明转化成了一个表达式,解析器不再以函数声明的方式处理函数a,而是作为一个函数表达式处理,也因此只有在程序执行到函数a时它才能被访问。
所以,任何消除函数声明和函数表达式间歧义的方法,都可以被解析器正确识别。比如:
var i = function(){return 10}();
1 && function(){return true}();
1, function(){alert('iifksp')}();
赋值,逻辑,甚至是逗号,各种操作符都可以告诉解析器,这个不是函数声明,它是个函数表达式。并且,对函数一元运算可以算的上是消除歧义最快的方式,感叹号只是其中之一,如果不在乎返回值,这些一元运算都是有效的:
!function(){alert('iifksp')}()
+function(){alert('iifksp')}()
-function(){alert('iifksp')}()
~function(){alert('iifksp')}()
甚至下面这些关键字,都能很好的工作:
void function(){alert('iifksp')}()
new function(){alert('iifksp')}()
delete function(){alert('iifksp')}()
最后,括号做的事情也是一样的,消除歧义才是它真正的工作,而不是把函数作为一个整体,所以无论括号括在声明上还是把整个函数都括在里面,都是合法的:
(function(){alert('iifksp')})()
(function(){alert('iifksp')}())
说了这么多,实则在说的一些都是最为基础的概念——语句,表达式,表达式语句,这些概念如同指针与指针变量一样容易产生混淆。虽然这种混淆对编程无表征影响,但却是一块绊脚石随时可能因为它而头破血流。
最后讨论下性能。我在jsperf上简单建立了一个测试: ,可以用不同浏览器访问,运行测试查看结果。我也同时将结果罗列如下表所示(由于我比较穷,测试配置有点丢人不过那也没办法:奔腾双核1.4G,2G内存,win7企业版):
!function(){;}()
10,975,198
+function(){;}()
21,553,847
12,135,960
-function(){;}()
21,553,847
12,135,960
~function(){;}()
(function(){;})()
12,135,960
(function(){;}())
12,135,960
void function(){;}()
12,135,960
new function(){;}()
delete function(){;}()
12,135,960
var i = function(){;}()
12,135,960
1 && function(){;}()
0 || function(){;}()
1 & function(){;}()
12,135,960
1 | function(){;}()
12,135,960
1 ^ function(){;}()
12,135,960
1, function(){;}()
12,135,960
可见不同的方式产生的结果并不相同,而且,差别很大,因浏览器而异。
但我们还是可以从中找出很多共性:new方法永远最慢——这也是理所当然的。其它方面很多差距其实不大,但有一点可以肯定的是,感叹号并非最为理想的选择。反观传统的括号,在测试里表现始终很快,在大多数情况下比感叹号更快——所以平时我们常用的方式毫无问题,甚至可以说是最优的。加减号在chrome表现惊人,而且在其他浏览器下也普遍很快,相比感叹号效果更好。
当然这只是个简单测试,不能说明问题。但有些结论是有意义的:括号和加减号最优。
但是为什么这么多开发者钟情于感叹号?我觉得这只是一个习惯问题,它们之间的优劣完全可以忽略。一旦习惯了一种代码风格,那么这种约定会使得程序从混乱变得可读。如果习惯了感叹号,我不得不承认,它比括号有更好的可读性。我不用在阅读时留意括号的匹配,也不用在编写时粗心遗忘——
当我也这么干然后嚷嚷着这居然又节省了一个字符而沾沾自喜的时候,却忘了自己仓皇翻出一本卷边的C语言教科书的窘迫和荒唐......任何人都有忘记的时候,当再捡起来的时候,捡起的就已经不单单是忘掉的东西了。
更新:如果你使用aptana,那么在使用(!+-)时要注意一点,它们会让aptana的解析失效,导致Outline窗口没有任何显示。但是就代码本身而言,其运行没有任何问题。
没有更多推荐了,濡備綍璁╀綘鐨凧avaScript浠g爜鏇村姞璇?箟鍖}

我要回帖

更多关于 js代码怎么用 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信