CSS不像其它高級語言同樣支持算術運算、變量、流程控制與面向對象特性,因此CSS樣式較多時會引發一些問題,如修改複雜,冗餘,某些別的語言很簡單的功能實現不了等。而javascript則是一種半面向對象的動態語言,有java的影子,有C的味道,中間有比其它語言多的糟粕,使用預處理辦法能夠解決這些問題。其中Less[les]與Sass是CSS的預處理技術,而CoffeeScript、TypeScript則是javascript的預處理技術。 javascript
Less是一種動態樣式語言,Less 是一門 CSS 預處理語言,它擴展了 CSS 語言,增長了變量、Mixin、函數等特性,使 CSS 更易維護和擴展。css
Less 將 CSS 賦予了動態語言的特性,如 變量, 繼承, 運算, 函數。LESS 既能夠在 客戶端 上運行 (支持IE 6+, Webkit, Firefox),也能夠藉助Node.js或者Rhino在服務端運行。 Less是一個JS庫,因此他能夠在客戶端運行,相對Sass則必須在服務端藉助Ruby運行html
中文網站: http://www.lesscss.net/java
英文官網: http://lesscss.orgnode
less源碼: https://github.com/cloudhead/less.jsjquery
github地址: https://github.com/less/less.jscss3
語法:@變量名:值;git
1)、以@做爲變量的起始標識,變量名由字母、數字、_和-組成
2)、沒有先定義後使用的規定;
3)、以最後定義的值爲最終值;
4)、可用於rule值、rule屬性、rule屬性部件、選擇器、選擇器部件、字符串拼接;
5)、定義時 "@變量名: 變量值;" 的形式;引用時採用 "@變量名" 或 "@{變量名}" 的形式;
6)、存在做用域,局部做用域優先級高於全局做用域。程序員
@color: #4d926f; #header { color: @color; } #header { color: #4d926f; } @color: #253636; @color: #ff3636; //覆蓋第一次的定義 #header {color: @color;} //屢次反覆解析 #header {color: #ff3636;}
編譯後:github
#header { color: #ff3636; } #header { color: #4d926f; } #header { color: #ff3636; } #header { color: #ff3636; }
a)、先安裝node.js(https://nodejs.org/en/)
b)、安裝less編譯器
npm install less -g
c)、安裝插件
d、配置
默認是正常的,若是發現Hbuilder不能自動翻譯則須要配置
頁面中直接引用less的源碼,使用javascript動態翻譯,這樣在開發階段很是方便,可是在運行階段會影響效率,建議在開發階段使用less.js在線處理,項目穩定運行時將less文件預處理。
步驟一:
下載到less.js動態處理.less文件的javascript腳本,下載地址: https://github.com/less/less.js
步驟二:
在頁面中引入樣式與less.js文件,以下:
<link rel="stylesheet/less" type="text/css" href="styles.less"> <script src="less.js" type="text/javascript"></script>
測試運行
示例代碼:
style1.less
/*1定義變量*/ @color:red; @bgColor:lightgreen; /*定義變量color,值爲red*/ .cls11{ color: @color; } @color:lightblue; /*從新定義,覆蓋前面的定義,後定義的起做用*/ .cls12 { background: @bgColor; border: 2px solid @color; }
de2.html
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Less</title> <link rel="stylesheet/less" type="text/css" href="css/style1.less"> <script src="js/less/less.min.js" type="text/javascript"></script> </head> <body> <div id="div1" class="cls12"> Hello Less </div> </body> </html>
運行效果:
從上圖能夠看出less.js將style1.less文件翻譯後變成了一個標準的CSS內部樣式表。
在線處理的效率低,預處理就是將less文件先翻譯成標準的CSS文件,再引入到項目中,處理的辦法有許多:
方法一:使用lessc
a)、請先在電腦上安裝node.js,下載地址: https://nodejs.org/en/
a)、安裝lessc
使用npm(node.js package management)node.js包管理器
在命令行模式下輸入安裝指令:npm install less -g
使用lessc翻譯less文件爲css文件:
lessc styles.less 顯示
lessc styles.less > styles.css 生成文件
參數 –x 普通壓縮
參數 -h 幫助
-x的壓縮方法已經被棄用,建議使用清理插件。
方法二:使用工具軟件
可以翻譯Less的工具軟件有很多,這裏介紹:Koala
Koala是一個開源的預處理語言圖形編譯工具,目前已支持Less、Sass、Compass與CoffeeScript。
功能特性:
多語言支持: 支持Less、Sass、Compass與CoffeeScript。
實時監聽與編譯: 在後臺監聽文件的變更,檢測到文件被修改後將自動進行編譯。
編譯選項支持: 能夠設置與自定義你須要的編譯選項。
壓縮支持: Less、Sass可直接編譯生成壓縮後的css代碼。
錯誤提示: 編譯中若是遇到錯誤,Koala將在右下角提示並顯示出具體的出錯地方,方便開發者快速定位。
跨平臺: Windows、Mac、Linux完美支持。
安裝Koala
在Koala官網根據你的系統平臺下載對應的版本。Linux系統要求已安裝好ruby運行環境。
下載地址: http://koala-app.com/
注意:路徑中不要使用中文,切記!
方法三:使用IDE插件
若是使用Eclipse,Hbuilder,Visual Studio等開發工具能夠安裝插件完成自動翻譯功能,這裏使用HBuilder,在工具->插件下能夠選擇安裝,以下圖所示:
使用方法:
新建Less文件,保存後會本身生成對應的CSS文件。
相似函數或宏
定義函數,@radius是參數,3px是默認值
.borderRadius(@radius:3px){
-moz-border-radius: @radius;
-webkit-border-radius: @radius;
border-radius: @radius;
}
使用函數,帶參數
#header { .borderRadius(10px); }
不帶參數使用默認參數
.btn { .borderRadius}
注意:
a)、能夠不使用參數 .wrap(){…} .pre{ .wrap },也可使用多個參數
b)、內置變量@arguments表明全部參數(運行時)的值 .boxShadow(@x:0,@y:0,@blur:1px,@color:#000){ box-shadow: @arguments; }
注意,在參數沒有默認值的前提下使用@arguments調用時必須賦值,不然會致使整個頁面內的less語法出錯而失效。
c)、Mixins必須使用ID或者類,即#xx或.xx,不然無效。
Less示例代碼:
/*混入(Mixins)*/ /*定義*/ .circle(@width:100px, @color:lightblue) { width: @width; height: @width; background: @color; border-radius: @width/2; float: left; } .boxShadow(@x:0, @y:0, @blur:1px, @color:#000) { box-shadow: @arguments; } /*調用*/ .cls21 { .circle(); /*默認值*/ } .cls22 { .circle(200px,lightgreen); /*帶參數*/ .boxShadow(5px,5px); } .cls23 { .circle(300px); /*帶一個參數*/ }
HTML頁面:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Less</title> <link rel="stylesheet" type="text/css" href="css/style2.css" /> </head> <body> <div id="div1" class="cls21"> </div> <div id="div1" class="cls22"> </div> <div id="div1" class="cls23"> </div> </body> </html>
翻譯結果:
/*調用*/ .cls21 { width: 100px; height: 100px; background: lightblue; border-radius: 50px; float: left;/*默認值*/ } .cls22 { width: 200px; height: 200px; background: lightgreen; border-radius: 100px; float: left; /*帶參數*/ box-shadow: 5px 5px 1px #000; } .cls23 { width: 300px; height: 300px; background: lightblue; border-radius: 150px; float: left;/*帶一個參數*/ } /*# sourceMappingURL=style2.css.map */
運行效果:
容許將多個CSS選擇器嵌套在一塊兒,&表示當前選擇器的父選擇器
#header {
&.fl{ float: left; }
.mln { margin-left: 0; }
}
生成
#header.fl{float: left;}
#header .mln {margin-left: 0;}
示例:
/*嵌套*/ #parent { color: red; .sub11 { background: green; } &.sub12 { width: 100px; } .sub13 { height: 200px; .sub131 { font-size: 10px; } } }
結果:
/*嵌套*/ #parent { color: red; } #parent .sub11 { background: green; } #parent.sub12 { width: 100px; } #parent .sub13 { height: 200px; } #parent .sub13 .sub131 { font-size: 10px; }
運算主要是針對任何數字、顏色、變量的操做,支持加、減、乘、除、()或者更復雜的綜合運算;
@init: #111111;
@transition: @init*2;
.switchColor { color: @transition; }
算術運算示例:
/*運算*/ @base: 5%; @filler: @base * 2; @other: @base + @filler; @base-color:lightblue; .cls41{ color: #888 / 4; background-color: @base-color + #111; height: 100% / 2 + @filler; }
運行結果:
.cls41 { color: #222222; background-color: #bee9f7; height: 60%; }
Less 提供了許多用於轉換顏色,處理字符串和進行算術運算的函數
.lightColor{lighten(@color, 10%); }
更多函數: http://www.lesscss.net/functions/
示例:
/*函數*/ .cls51 { /*將一個資源內嵌到樣式文件,若是開啓了ieCompat選項,並且資源文件的體積過大,或者是在瀏覽器中使用,則會使用url()進行回退。若是沒有指定MIME,則Node.js會使用MIME包來決定正確的MIME。*/ background: data-uri('../img/yes.gif') no-repeat; height: 20px; } .cls52 { /*增長必定數值的顏色亮度。*/ background: lighten(blue,20%); }
翻譯結果:
/*函數*/ .cls51 { /*將一個資源內嵌到樣式文件,若是開啓了ieCompat選項,並且資源文件的體積過大,或者是在瀏覽器中使用,則會使用url()進行回退。若是沒有指定MIME,則Node.js會使用MIME包來決定正確的MIME。*/ background: url("data:null;base64,R0lGODlhDAAMAKIAAMznjyJ6Gu732TKGFq7ZTF+nDI7JBf///yH5BAAAAAAALAAAAAAMAAwAAAM8eCdAZgQItdy7RAlXyhidBhjdEAQD1ZDHGVDQUyivMlws1d6xR6EFyKi06xgkHA8oSJhscI8mhWGJTA4JADs=") no-repeat; height: 20px; } .cls52 { /*增長必定數值的顏色亮度。*/ background: #6666ff; }
運行效果:
示例代碼:
/*繼承*/ .animal { background-color: black; color: white; } .bear { &:extend(.animal); background-color: brown; } .mouse{ &:extend(.animal); }
翻譯結果:
/*繼承*/ .animal, .bear, .mouse { background-color: black; color: white; } .bear { background-color: brown; }
同一級的變量後者覆蓋前者,內部變量優先級高於外部變量,變量只在同一個文件中生效。
示例:
/*做用域*/ @len:10px; .cls61{ @len:20px; height:@len; } .cls62{ width:@len; } @len:30px; .cls63{ height: @len; }
結果:
.cls61 { height: 20px; } .cls62 { width: 30px; } .cls63 { height: 30px; }
示例:
/*註釋*/ .cls71{ width: 100px; //單行註釋,CSS中不容許單行註釋,Less容許 height:100px; /* 多行註釋,CSS與Less都容許 */ }
結果:
/*註釋*/ .cls71 { width: 100px; height: 100px;/* 多行註釋,CSS與Less都容許 */ }
在Less中,混合能夠調用它自身。這樣,當一個混合遞歸調用本身,再結合Guard表達式和模式匹配這兩個特性,就能夠寫出循環結構。
less源碼:
.loop(@counter) when (@counter > 0) { .loop((@counter - 1)); // 遞歸調用自身 width: (10px * @counter); // 每次調用時產生的樣式代碼 } div { .loop(3); // 調用循環 }
生成css:
div { width: 30px; width: 20px; width: 10px; }
less源碼(生成柵格系統):
.generate-columns(5); .generate-columns(@n, @i: 1) when (@i =< @n) { .column-@{i} { width: (@i * 100% / @n); } .generate-columns(@n, (@i + 1)); }
生成css:
.column-1 { width: 20%; } .column-2 { width: 40%; } .column-3 { width: 60%; } .column-4 { width: 80%; } .column-5 { width: 100%; }
style.less:
/*1.三、變量**/ @color: red; /*1.四、混入(Mixins)**/ .circle(@length: 100px, @color: lightblue) { width: @length; height: @length; background: @color; border-radius: @length/3; float: left; } .boxshadow(@x: 3px, @y: 3px, @blur: 3px, @color: #999) { box-shadow: @arguments; box-shadow: @x @y @blur @color; } .c1 { .circle(); /**默認參數*/ } .c2 { .circle(200px, lightgreen); /**指定全部參數*/ } .c3 { .circle(300px); /**指定部分*/ } .c4 { .circle(400px); /**指定部分*/ .boxshadow(5px, 5px, 5px, #00f); } .c5 { .circle(500px); /**指定部分*/ .boxshadow(); } /*1.五、嵌套 **/ #main { color: @color; .sub1 { width: 100px; .sub11 { background: #00f; } } &.sub2 { height: 100px; } } @color: blue; /*1.六、運算**/ @i: 10rem; @pcolor: blue; @color: #0000ff; .cls16 { width: @i+10/2; background: #000111+#111000; color: @pcolor+#00ff00; } /*1.七、函數**/ .lightColor { width: floor(2.6)px; } .bg { background: data-uri('dot2.gif'); } /*1.八、繼承 **/ .animal { color: black; background: white; } .duck { &:extend(.animal); color: yellow; } .tduck { &:extend(.duck); min-height: 100px; } .pig { &:extend(.animal); } /*1.九、做用域*/ @len: 10px; .cls61 { @len: 20px; height: @len; } @len: 30px; .cls62 { width: @len; } @len: 40px; .cls63 { height: @len; } @len: 50px; /*1.十、註釋**/ .c { width: 100px; //寬100px } /*1.十一、循環*/ .loop(@counter) when (@counter > 0) { width: (10px * @counter); // 每次調用時產生的樣式代碼 .loop((@counter - 1)); // 遞歸調用自身 } div { .loop(3); // 調用循環 } .generate-columns(5); .generate-columns(@n, @i: 1) when (@i =< @n) { .column-@{i} { width: (@i * 100% / @n); } .generate-columns(@n, (@i + 1)); }
style.css:
/*1.三、變量**/ /*1.四、混入(Mixins)**/ .c1 { width: 100px; height: 100px; background: lightblue; border-radius: 33.33333333px; float: left; /**默認參數*/ } .c2 { width: 200px; height: 200px; background: lightgreen; border-radius: 66.66666667px; float: left; /**指定全部參數*/ } .c3 { width: 300px; height: 300px; background: lightblue; border-radius: 100px; float: left; /**指定部分*/ } .c4 { width: 400px; height: 400px; background: lightblue; border-radius: 133.33333333px; float: left; /**指定部分*/ box-shadow: 5px 5px 5px #00f; } .c5 { width: 500px; height: 500px; background: lightblue; border-radius: 166.66666667px; float: left; /**指定部分*/ box-shadow: 3px 3px 3px #999; } /*1.五、嵌套 **/ #main { color: #0000ff; } #main .sub1 { width: 100px; } #main .sub1 .sub11 { background: #00f; } #main.sub2 { height: 100px; } /*1.六、運算**/ .cls16 { width: 15rem; background: #111111; color: #00ffff; } /*1.七、函數**/ .lightColor { width: 2 px; } .bg { background: url("data:image/gif;base64,R0lGODlhCQALAJEAAAAAAP///wCO/////yH5BAEAAAMALAAAAAAJAAsAAAITnI8naeLsllq0vlhHnhJFpoFMAQA7"); } /*1.八、繼承 **/ .animal, .duck, .pig, .tduck { color: black; background: white; } .duck, .tduck { color: yellow; } .tduck { min-height: 100px; } /*1.九、做用域*/ .cls61 { height: 20px; } .cls62 { width: 50px; } .cls63 { height: 50px; } /*1.十、註釋**/ .c { width: 100px; } /*1.十一、循環*/ div { width: 30px; width: 20px; width: 10px; } .column-1 { width: 20%; } .column-2 { width: 40%; } .column-3 { width: 60%; } .column-4 { width: 80%; } .column-5 { width: 100%; }
Sass與Less相似相似也是一種CSS的預編譯語言,他出現的更晚,但功能更增強大,Sass 有兩種語法。 第一種被稱爲 SCSS (Sassy CSS),是一個 CSS3 語法的擴充版本;第二種比較老的語法成爲縮排語法(或者就稱爲 "Sass"), 提供了一種更簡潔的 CSS 書寫方式特色以下:
特色:
1)、不能直接在頁面中解析,須要使用ruby預先翻譯成css文件,而Less能夠在線動態翻譯。
2)、Sass功能更增強大,擁有流控語句等Less不具有的功能
3)、徹底兼容 CSS3,在 CSS 語言基礎上添加了擴展功能,好比變量、嵌套 (nesting)、混合 (mixin)
在使用時Sass的後綴名爲scss,本文所有使用scss的語法,能夠安裝Koala直接解析,不須要去搭建ruby環境,Koala已封裝好。
下載地址: http://koala-app.com/
sass中能夠定義變量,方便統一修改和維護
Sass代碼:
/*變量*/ $width:1004px; $color:blue; .cls11 { width: $width; height: $width/2; background: $color; } $width:100px; $color:red; .cls12 { $color:green; width: $width; height: $width/2; background: $color; }
CSS代碼:
.cls11 { width: 1004px; height: 502px; background: blue; } .cls12 { width: 100px; height: 50px; background: green; }
sass能夠進行選擇器的嵌套,表示層級關係,看起來很優雅整齊。
Sass代碼:
.cls21 { width: 100px; .cls22{ height: 200px; } .cls23 { color:blue; } }
CSS代碼:
.cls21 { width: 100px; } .cls21 .cls22 { height: 200px; } .cls21 .cls23 { color: blue; }
複雜的嵌套:
.news{ //忽略root嵌套 @at-root .news_title{ width: 10px; } // 合併嵌套 .news_content{ width: 20px; } //組合嵌套 &_content1{ width: 20px; &_content2{ width: 20px; } } }
結果:
.news .news_content { // 在根節點.news下 width: 20px; } .news_content1 { // 組合了根節點.news成爲當前標籤的一部分 width: 20px; } .news_content1_content2 { // 多層組合&值爲上一層的標籤名稱 width: 20px; }
sass中如導入其餘sass文件,最後編譯爲一個css文件,優於純css的@import
reset.scss
$zero:0; $PI:3.14; * { margin: $zero; padding: $zero; } body,html{ height: 100%; }
Sass代碼:
@import "reset"; .cls31 { /*height: zero; */ /*error*/ }
CSS代碼:
* { margin: 0; padding: 0; } body, html { height: 100%; } .cls31 { /*height: zero; */ /*error*/ }
sass中可用mixin定義一些代碼片斷,且可傳參數,方便往後根據需求調用。今後處理css3的前綴兼容輕鬆便捷。定義時使用關鍵字@mixin,調用時使用@include
SCSS樣式:
@mixin circle($size:100px,$color:lightblue){ width: $size; height: $size; border-radius: $size/2; background: $color; } .cls41{ @include circle(); } .cls42{ @include circle(150px); } .cls43{ @include circle(200px,lightgreen); }
CSS樣式:
.cls41 { width: 100px; height: 100px; border-radius: 50px; background: lightblue; } .cls42 { width: 150px; height: 150px; border-radius: 75px; background: lightblue; } .cls43 { width: 200px; height: 200px; border-radius: 100px; background: lightgreen; }
sass可經過@extend來實現代碼組合聲明,使代碼更加優越簡潔。
SCSS樣式:
.state { background: blue; border: 1px solid lightblue; } .success{ @extend .state; background: green; } .error { @extend .state; border: 2px solid red; }
CSS樣式:
.state, .success, .error { background: blue; border: 1px solid lightblue; } .success { background: green; } .error { border: 2px solid red; }
SCSS樣式:
.cls61 { width: (100px+10px)/2-20px%7px+1px*8; }
CSS樣式:
.cls61 { width: 57px; }
sass中集成了大量的顏色函數,讓變換顏色更加簡單。
SCSS樣式:
$pcolor: #999ccc; .cls71 a { color: $pcolor; &:hover { background: darken($pcolor,15%); /*變暗15%*/ color: lighten($pcolor,5%); /*變亮5%*/ }
CSS樣式:
.cls71 a { color: #999ccc; } .cls71 a:hover { background: #666bb3; color: #aaacd5; }
rgb($red, $green, $blue) //根據RGB中的三個值計算出一個顏色;
rgba($red, $green, $blue, $alpha) //根據RGB中紅、綠、藍和透明度計算出一個顏色;
red($color) //獲取RGB中的紅色值;
green($color) //獲取RGB中的綠色值;
blue($color) //獲取RGB中的藍色值;
mix($color1, $color2, [$weight]) //混合兩種顏色;
hsl(hue,saturation, $lightness): 根據色相、飽和度和亮度的值返回對應的HEX顏色
hsla(hue,saturation, lightness,alpha): 根據色相、飽和度、亮度和透明度的值返回對應的HEX顏色
hue($color):從HEX顏色值中取得色相值
saturation($color): 從一個HEX顏色值中取得飽和度值
lightness($color):從一個HEX顏色值中取得亮度值
ajust-hue(color,degrees):經過改變一個顏色的色相值,建立一個新的顏色
lighten(color,amount):經過改變顏色的亮度值,讓顏色變亮,建立一個一個新的顏色
darken(color,amount):經過改變顏色的亮度值,讓顏色變暗,建立一個一個新的顏色
saturate(color,amount):經過改變顏色的飽和度值,讓顏色更飽和,從而建立一個新的顏色
desaturate(color,amount):經過改變顏色的飽和度值,讓顏色更少的飽和,從而建立出一個新的顏色
grayscale(color):將一個顏色變成灰色,至關於desaturate(color,100%);
complement(color):返回一個補充色,至關於adjust?hue(color,180deg);
invert($color):反回一個反相色,紅、綠、藍色值倒過來,而透明度不變
alpha($color)/opacity($color):得到透明度值
rgba($color,alpha):改變顏色的透明度值
opacify($color,$amount)/fade-in($color,$amount):使顏色更不透明
transparentize($color,$amount)/fade-out($color,$amount):使顏色更加透明
sass中和其它程序語言同樣也擁有流程控制語句,如if,for,each,while,指令,函數等。
SCSS樣式:
$blur: lightblue; @for $i from 1 through 10 { .font-#{$i} { /*計算字體大小*/ font-size: 12px+$i*2px; /*顏色變暗*/ color: darken($blur,$i*2); /*若是i是3的倍數,則下劃線*/ @if $i%3==0 { text-decoration: underline; } } }
CSS樣式:
/*8*/ .font-1 { font-size: 14px; color: #a5d4e4; } .font-2 { font-size: 16px; color: #9dd1e1; } .font-3 { font-size: 18px; color: #96cddf; text-decoration: underline; } .font-4 { font-size: 20px; color: #8ec9dc; } .font-5 { font-size: 22px; color: #86c5da; } .font-6 { font-size: 24px; color: #7ec2d8; text-decoration: underline; } .font-7 { font-size: 26px; color: #76bed5; } .font-8 { font-size: 28px; color: #6ebad3; } .font-9 { font-size: 30px; color: #67b7d1; text-decoration: underline; } .font-10 { font-size: 32px; color: #5fb3ce; }
HTML頁面:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title></title> <link rel="stylesheet" type="text/css" href="css/style3.css" /> </head> <body style="padding: 10px;"> <div class="font-1">Hello SASS!</div> <div class="font-2">Hello SASS!</div> <div class="font-3">Hello SASS!</div> <div class="font-4">Hello SASS!</div> <div class="font-5">Hello SASS!</div> <div class="font-6">Hello SASS!</div> <div class="font-7">Hello SASS!</div> <div class="font-8">Hello SASS!</div> <div class="font-9">Hello SASS!</div> <div class="font-10">Hello SASS!</div> </body> </html>
運行效果:
更多內容請參考:https://www.sass.hk http://sass.bootcss.com/ http://sass-lang.com/
javascript變得日益重要,但有不少明顯的缺點,藉助一種中間語言轉譯出優雅的javascript是解決這些問題的方法。如CoffeeScript,TypeScript。
Coffee Script是JavaScript的轉譯語言。瞭解JavaScript的發展歷程:https://news.cnblogs.com/n/558565/。
Coffee的特色:
CoffeeScript語法相似 Ruby ,能夠被編譯成 JavaScript
CoffeeScript取JavaScript之精華,而拋棄了諸如全局變量聲明、with等容易出錯的部分
CoffeeScript是JavaScript與程序員之間的橋樑,程序員看到的是優雅的CoffeeScript接口,使得編程更簡潔,寫法更隨意
更少,更緊湊,和更清晰的代碼
經過規避和改變對JavaScript中不良部分的使用,只留下精華,讓代碼減小出錯率,更容易維護
在不少經常使用模式的實現上採用了JavaScript中的最佳實踐
CoffeeScript生成的JavaScript代碼均可以徹底經過JSLint的檢測
中文網: http://coffee-script.org/
源碼:https://github.com/coffee-js/coffee-script
CoffeeScript 編譯器自己是 CoffeeScript 寫的, 使用了 Jison parser generator. 命令行版本的coffee是一個實用的 Node.js 工具。
安裝前你須要最新穩定版 Node.js, 和 npm (Node Package Manager)。藉助 npm 能夠安裝 CoffeeScript:
npm install -g coffee-script
安裝以後, 你應該能夠運行 coffee 命令以執行腳本, 編譯 .coffee 文件到 .js 文件, 和提供一個交互式的 REPL. coffee 命令有下列參數:
-c, --compile 編譯一個 .coffee 腳本到一個同名的 .js 文件.
-m, --map 隨 JavaScript 文件一塊兒生成 source maps. 而且在 JavaScript 里加上 sourceMappingURL 指令.
-i, --interactive 啓動一個交互式的 CoffeeScript 會話用來嘗試一些代碼片斷. 等同於執行 coffee 而不加參數.
-o, --output [DIR] 將全部編譯後的 JavaScript 文件寫到指定文件夾. 與 --compile 或 --watch 搭配使用.
-j, --join [FILE] 編譯以前, 按參數傳入順序鏈接全部腳本到一塊兒, 編譯後寫到指定的文件. 對於編譯大型項目有用.
-w, --watch 監視文件改變, 任何文件更新時從新執行命令.
-p, --print JavaScript 直接打印到 stdout 而不是寫到一個文件.
-s, --stdio 將 CoffeeScript 傳遞到 STDIN 後從 STDOUT 獲取 JavaScript. 對其餘語言寫的進程有好處. 好比:
cat src/cake.coffee | coffee -sc
-l, --literate 將代碼做爲 Literate CoffeeScript 解析. 只會在從 stdio 直接傳入代碼或者處理某些沒有後綴的文件名須要寫明這點.
-e, --eval 直接從命令行編譯和打印一小段 CoffeeScript. 好比:
coffee -e "console.log num for num in [10..1]"
-b, --bare 編譯到 JavaScript 時去掉頂層函數的包裹.
-t, --tokens 不對 CoffeeScript 進行解析, 僅僅進行 lex, 打印出 token stream: [IDENTIFIER square] [ASSIGN =] [PARAM_START (] ...
-n, --nodes 不對 CoffeeScript 進行編譯, 僅僅 lex 和解析, 打印 parse tree:
--nodejs node 命令有一些實用的參數, 好比
--debug, --debug-brk, --max-stack-size, 和 --expose-gc. 用這個參數直接把參數轉發到 Node.js. 重複使用 --nodejs 來傳遞多個參數.
一、編輯coffee腳本,後綴爲coffee,代碼以下:
# 賦值: number = 42 opposite = true # 條件: number = -42 if opposite # 函數: square = (x) -> x * x # 數組: list = [1, 2, 3, 4, 5] # 對象: math = root: Math.sqrt square: square cube: (x) -> x * square x # Splats: race = (winner, runners...) -> print winner, runners # 存在性: alert "I knew it!" if elvis? # 數組 推導(comprehensions): cubes = (math.cube num for num in list)
將coffeescript翻譯成javascript的方法以下:
a)、使用IDE插件直接翻譯
翻譯成javascript後的腳本以下:
(function() { var cubes, list, math, num, number, opposite, race, square, slice = [].slice; number = 42; opposite = true; if (opposite) { number = -42; } square = function(x) { return x * x; }; list = [1, 2, 3, 4, 5]; math = { root: Math.sqrt, square: square, cube: function(x) { return x * square(x); } }; race = function() { var runners, winner; winner = arguments[0], runners = 2 <= arguments.length ? slice.call(arguments, 1) : []; return print(winner, runners); }; if (typeof elvis !== "undefined" && elvis !== null) { alert("I knew it!"); } cubes = (function() { var i, len, results; results = []; for (i = 0, len = list.length; i < len; i++) { num = list[i]; results.push(math.cube(num)); } return results; })(); }).call(this);
b)、命令行翻譯
翻譯後的結果與上文相同,-c是參數表示編譯的意思,-w是監聽文件的變化,文件發生變化後將當即編譯。
面向對象示例:
class Animal constructor: (@name) -> move: (meters) -> alert @name + " moved #{meters}m." class Snake extends Animal move: -> alert "Slithering..." super 5 class Horse extends Animal move: -> alert "Galloping..." super 45 sam = new Snake "Sammy the Python" tom = new Horse "Tommy the Palomino" sam.move() tom.move()
翻譯後的javascript:
(function() { var Animal, Horse, Snake, sam, tom, extend = function(child, parent) { for(var key in parent) { if(hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }, hasProp = {}.hasOwnProperty; Animal = (function() { function Animal(name) { this.name = name; } Animal.prototype.move = function(meters) { return alert(this.name + (" moved " + meters + "m.")); }; return Animal; })(); Snake = (function(superClass) { extend(Snake, superClass); function Snake() { return Snake.__super__.constructor.apply(this, arguments); } Snake.prototype.move = function() { alert("Slithering..."); return Snake.__super__.move.call(this, 5); }; return Snake; })(Animal); Horse = (function(superClass) { extend(Horse, superClass); function Horse() { return Horse.__super__.constructor.apply(this, arguments); } Horse.prototype.move = function() { alert("Galloping..."); return Horse.__super__.move.call(this, 45); }; return Horse; })(Animal); sam = new Snake("Sammy the Python"); tom = new Horse("Tommy the Palomino"); sam.move(); tom.move(); }).call(this);
TypeScript是一種由微軟開發的自由和開源的編程語言,它是JavaScript的一個超集,擴展了JavaScript的語法,並且本質上向這個語言添加了可選的靜態類型和基於類的面向對象編程。安德斯·海爾斯伯格,C#的首席架構師,工做於TypeScript的開發。
官網:http://www.typescriptlang.org/
github:https://github.com/Microsoft/TypeScript
a)、在node.js環境下安裝typescript,npm install -g typescript
b)、使用Microsoft指定的編輯器或IDE如,VS與微軟Visual Studio Code 免費跨平臺代碼編輯器,安裝相應的插件。
編寫typescript源代碼,greeter.ts:
class Greeter { constructor(public greeting: string) { } greet() { return "<h1>" + this.greeting + "</h1>"; } }; var greeter = new Greeter("Hello, world!"); document.body.innerHTML = greeter.greet();
使用tsc greeter.ts編譯生成javascript greeter.js腳本:
var Greeter = (function () { function Greeter(greeting) { this.greeting = greeting; } Greeter.prototype.greet = function () { return "<h1>" + this.greeting + "</h1>"; }; return Greeter; }()); ; var greeter = new Greeter("Hello, world!"); document.body.innerHTML = greeter.greet();
新建一個頁面測試:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>TypeScript Hello World!</title> </head> <body> <script src="typescript/greeter.js" type="text/javascript" charset="utf-8"></script> </body> </html>
運行結果:
示例2,raytracer.ts代碼:
class Vector { constructor(public x: number, public y: number, public z: number) { } static times(k: number, v: Vector) { return new Vector(k * v.x, k * v.y, k * v.z); } static minus(v1: Vector, v2: Vector) { return new Vector(v1.x - v2.x, v1.y - v2.y, v1.z - v2.z); } static plus(v1: Vector, v2: Vector) { return new Vector(v1.x + v2.x, v1.y + v2.y, v1.z + v2.z); } static dot(v1: Vector, v2: Vector) { return v1.x * v2.x + v1.y * v2.y + v1.z * v2.z; } static mag(v: Vector) { return Math.sqrt(v.x * v.x + v.y * v.y + v.z * v.z); } static norm(v: Vector) { var mag = Vector.mag(v); var div = (mag === 0) ? Infinity : 1.0 / mag; return Vector.times(div, v); } static cross(v1: Vector, v2: Vector) { return new Vector(v1.y * v2.z - v1.z * v2.y, v1.z * v2.x - v1.x * v2.z, v1.x * v2.y - v1.y * v2.x); } } class Color { constructor(public r: number, public g: number, public b: number) { } static scale(k: number, v: Color) { return new Color(k * v.r, k * v.g, k * v.b); } static plus(v1: Color, v2: Color) { return new Color(v1.r + v2.r, v1.g + v2.g, v1.b + v2.b); } static times(v1: Color, v2: Color) { return new Color(v1.r * v2.r, v1.g * v2.g, v1.b * v2.b); } static white = new Color(1.0, 1.0, 1.0); static grey = new Color(0.5, 0.5, 0.5); static black = new Color(0.0, 0.0, 0.0); static background = Color.black; static defaultColor = Color.black; static toDrawingColor(c: Color) { var legalize = d => d > 1 ? 1 : d; return { r: Math.floor(legalize(c.r) * 255), g: Math.floor(legalize(c.g) * 255), b: Math.floor(legalize(c.b) * 255) } } } class Camera { public forward: Vector; public right: Vector; public up: Vector; constructor(public pos: Vector, lookAt: Vector) { var down = new Vector(0.0, -1.0, 0.0); this.forward = Vector.norm(Vector.minus(lookAt, this.pos)); this.right = Vector.times(1.5, Vector.norm(Vector.cross(this.forward, down))); this.up = Vector.times(1.5, Vector.norm(Vector.cross(this.forward, this.right))); } } interface Ray { start: Vector; dir: Vector; } interface Intersection { thing: Thing; ray: Ray; dist: number; } interface Surface { diffuse: (pos: Vector) => Color; specular: (pos: Vector) => Color; reflect: (pos: Vector) => number; roughness: number; } interface Thing { intersect: (ray: Ray) => Intersection; normal: (pos: Vector) => Vector; surface: Surface; } interface Light { pos: Vector; color: Color; } interface Scene { things: Thing[]; lights: Light[]; camera: Camera; } class Sphere implements Thing { public radius2: number; constructor(public center: Vector, radius: number, public surface: Surface) { this.radius2 = radius * radius; } normal(pos: Vector): Vector { return Vector.norm(Vector.minus(pos, this.center)); } intersect(ray: Ray) { var eo = Vector.minus(this.center, ray.start); var v = Vector.dot(eo, ray.dir); var dist = 0; if (v >= 0) { var disc = this.radius2 - (Vector.dot(eo, eo) - v * v); if (disc >= 0) { dist = v - Math.sqrt(disc); } } if (dist === 0) { return null; } else { return { thing: this, ray: ray, dist: dist }; } } } class Plane implements Thing { public normal: (pos: Vector) =>Vector; public intersect: (ray: Ray) =>Intersection; constructor(norm: Vector, offset: number, public surface: Surface) { this.normal = function(pos: Vector) { return norm; } this.intersect = function(ray: Ray): Intersection { var denom = Vector.dot(norm, ray.dir); if (denom > 0) { return null; } else { var dist = (Vector.dot(norm, ray.start) + offset) / (-denom); return { thing: this, ray: ray, dist: dist }; } } } } module Surfaces { export var shiny: Surface = { diffuse: function(pos) { return Color.white; }, specular: function(pos) { return Color.grey; }, reflect: function(pos) { return 0.7; }, roughness: 250 } export var checkerboard: Surface = { diffuse: function(pos) { if ((Math.floor(pos.z) + Math.floor(pos.x)) % 2 !== 0) { return Color.white; } else { return Color.black; } }, specular: function(pos) { return Color.white; }, reflect: function(pos) { if ((Math.floor(pos.z) + Math.floor(pos.x)) % 2 !== 0) { return 0.1; } else { return 0.7; } }, roughness: 150 } } class RayTracer { private maxDepth = 5; private intersections(ray: Ray, scene: Scene) { var closest = +Infinity; var closestInter: Intersection = undefined; for (var i in scene.things) { var inter = scene.things[i].intersect(ray); if (inter != null && inter.dist < closest) { closestInter = inter; closest = inter.dist; } } return closestInter; } private testRay(ray: Ray, scene: Scene) { var isect = this.intersections(ray, scene); if (isect != null) { return isect.dist; } else { return undefined; } } private traceRay(ray: Ray, scene: Scene, depth: number): Color { var isect = this.intersections(ray, scene); if (isect === undefined) { return Color.background; } else { return this.shade(isect, scene, depth); } } private shade(isect: Intersection, scene: Scene, depth: number) { var d = isect.ray.dir; var pos = Vector.plus(Vector.times(isect.dist, d), isect.ray.start); var normal = isect.thing.normal(pos); var reflectDir = Vector.minus(d, Vector.times(2, Vector.times(Vector.dot(normal, d), normal))); var naturalColor = Color.plus(Color.background, this.getNaturalColor(isect.thing, pos, normal, reflectDir, scene)); var reflectedColor = (depth >= this.maxDepth) ? Color.grey : this.getReflectionColor(isect.thing, pos, normal, reflectDir, scene, depth); return Color.plus(naturalColor, reflectedColor); } private getReflectionColor(thing: Thing, pos: Vector, normal: Vector, rd: Vector, scene: Scene, depth: number) { return Color.scale(thing.surface.reflect(pos), this.traceRay({ start: pos, dir: rd }, scene, depth + 1)); } private getNaturalColor(thing: Thing, pos: Vector, norm: Vector, rd: Vector, scene: Scene) { var addLight = (col, light) => { var ldis = Vector.minus(light.pos, pos); var livec = Vector.norm(ldis); var neatIsect = this.testRay({ start: pos, dir: livec }, scene); var isInShadow = (neatIsect === undefined) ? false : (neatIsect <= Vector.mag(ldis)); if (isInShadow) { return col; } else { var illum = Vector.dot(livec, norm); var lcolor = (illum > 0) ? Color.scale(illum, light.color) : Color.defaultColor; var specular = Vector.dot(livec, Vector.norm(rd)); var scolor = (specular > 0) ? Color.scale(Math.pow(specular, thing.surface.roughness), light.color) : Color.defaultColor; return Color.plus(col, Color.plus(Color.times(thing.surface.diffuse(pos), lcolor), Color.times(thing.surface.specular(pos), scolor))); } } return scene.lights.reduce(addLight, Color.defaultColor); } render(scene, ctx, screenWidth, screenHeight) { var getPoint = (x, y, camera) => { var recenterX = x =>(x - (screenWidth / 2.0)) / 2.0 / screenWidth; var recenterY = y => - (y - (screenHeight / 2.0)) / 2.0 / screenHeight; return Vector.norm(Vector.plus(camera.forward, Vector.plus(Vector.times(recenterX(x), camera.right), Vector.times(recenterY(y), camera.up)))); } for (var y = 0; y < screenHeight; y++) { for (var x = 0; x < screenWidth; x++) { var color = this.traceRay({ start: scene.camera.pos, dir: getPoint(x, y, scene.camera) }, scene, 0); var c = Color.toDrawingColor(color); ctx.fillStyle = "rgb(" + String(c.r) + ", " + String(c.g) + ", " + String(c.b) + ")"; ctx.fillRect(x, y, x + 1, y + 1); } } } } function defaultScene(): Scene { return { things: [new Plane(new Vector(0.0, 1.0, 0.0), 0.0, Surfaces.checkerboard), new Sphere(new Vector(0.0, 1.0, -0.25), 1.0, Surfaces.shiny), new Sphere(new Vector(-1.0, 0.5, 1.5), 0.5, Surfaces.shiny)], lights: [{ pos: new Vector(-2.0, 2.5, 0.0), color: new Color(0.49, 0.07, 0.07) }, { pos: new Vector(1.5, 2.5, 1.5), color: new Color(0.07, 0.07, 0.49) }, { pos: new Vector(1.5, 2.5, -1.5), color: new Color(0.07, 0.49, 0.071) }, { pos: new Vector(0.0, 3.5, 0.0), color: new Color(0.21, 0.21, 0.35) }], camera: new Camera(new Vector(3.0, 2.0, 4.0), new Vector(-1.0, 0.5, 0.0)) }; } function exec() { var canv = document.createElement("canvas"); canv.width = 256; canv.height = 256; document.body.appendChild(canv); var ctx = canv.getContext("2d"); var rayTracer = new RayTracer(); return rayTracer.render(defaultScene(), ctx, canv.width, canv.height); } exec();
編譯生成後的raytracer.js代碼:
var Vector = (function() { function Vector(x, y, z) { this.x = x; this.y = y; this.z = z; } Vector.times = function(k, v) { return new Vector(k * v.x, k * v.y, k * v.z); }; Vector.minus = function(v1, v2) { return new Vector(v1.x - v2.x, v1.y - v2.y, v1.z - v2.z); }; Vector.plus = function(v1, v2) { return new Vector(v1.x + v2.x, v1.y + v2.y, v1.z + v2.z); }; Vector.dot = function(v1, v2) { return v1.x * v2.x + v1.y * v2.y + v1.z * v2.z; }; Vector.mag = function(v) { return Math.sqrt(v.x * v.x + v.y * v.y + v.z * v.z); }; Vector.norm = function(v) { var mag = Vector.mag(v); var div = (mag === 0) ? Infinity : 1.0 / mag; return Vector.times(div, v); }; Vector.cross = function(v1, v2) { return new Vector(v1.y * v2.z - v1.z * v2.y, v1.z * v2.x - v1.x * v2.z, v1.x * v2.y - v1.y * v2.x); }; return Vector; }()); var Color = (function() { function Color(r, g, b) { this.r = r; this.g = g; this.b = b; } Color.scale = function(k, v) { return new Color(k * v.r, k * v.g, k * v.b); }; Color.plus = function(v1, v2) { return new Color(v1.r + v2.r, v1.g + v2.g, v1.b + v2.b); }; Color.times = function(v1, v2) { return new Color(v1.r * v2.r, v1.g * v2.g, v1.b * v2.b); }; Color.toDrawingColor = function(c) { var legalize = function(d) { return d > 1 ? 1 : d; }; return { r: Math.floor(legalize(c.r) * 255), g: Math.floor(legalize(c.g) * 255), b: Math.floor(legalize(c.b) * 255) }; }; return Color; }()); Color.white = new Color(1.0, 1.0, 1.0); Color.grey = new Color(0.5, 0.5, 0.5); Color.black = new Color(0.0, 0.0, 0.0); Color.background = Color.black; Color.defaultColor = Color.black; var Camera = (function() { function Camera(pos, lookAt) { this.pos = pos; var down = new Vector(0.0, -1.0, 0.0); this.forward = Vector.norm(Vector.minus(lookAt, this.pos)); this.right = Vector.times(1.5, Vector.norm(Vector.cross(this.forward, down))); this.up = Vector.times(1.5, Vector.norm(Vector.cross(this.forward, this.right))); } return Camera; }()); var Sphere = (function() { function Sphere(center, radius, surface) { this.center = center; this.surface = surface; this.radius2 = radius * radius; } Sphere.prototype.normal = function(pos) { return Vector.norm(Vector.minus(pos, this.center)); }; Sphere.prototype.intersect = function(ray) { var eo = Vector.minus(this.center, ray.start); var v = Vector.dot(eo, ray.dir); var dist = 0; if(v >= 0) { var disc = this.radius2 - (Vector.dot(eo, eo) - v * v); if(disc >= 0) { dist = v - Math.sqrt(disc); } } if(dist === 0) { return null; } else { return { thing: this, ray: ray, dist: dist }; } }; return Sphere; }()); var Plane = (function() { function Plane(norm, offset, surface) { this.surface = surface; this.normal = function(pos) { return norm; }; this.intersect = function(ray) { var denom = Vector.dot(norm, ray.dir); if(denom > 0) { return null; } else { var dist = (Vector.dot(norm, ray.start) + offset) / (-denom); return { thing: this, ray: ray, dist: dist }; } }; } return Plane; }()); var Surfaces; (function(Surfaces) { Surfaces.shiny = { diffuse: function(pos) { return Color.white; }, specular: function(pos) { return Color.grey; }, reflect: function(pos) { return 0.7; }, roughness: 250 }; Surfaces.checkerboard = { diffuse: function(pos) { if((Math.floor(pos.z) + Math.floor(pos.x)) % 2 !== 0) { return Color.white; } else { return Color.black; } }, specular: function(pos) { return Color.white; }, reflect: function(pos) { if((Math.floor(pos.z) + Math.floor(pos.x)) % 2 !== 0) { return 0.1; } else { return 0.7; } }, roughness: 150 }; })(Surfaces || (Surfaces = {})); var RayTracer = (function() { function RayTracer() { this.maxDepth = 5; } RayTracer.prototype.intersections = function(ray, scene) { var closest = +Infinity; var closestInter = undefined; for(var i in scene.things) { var inter = scene.things[i].intersect(ray); if(inter != null && inter.dist < closest) { closestInter = inter; closest = inter.dist; } } return closestInter; }; RayTracer.prototype.testRay = function(ray, scene) { var isect = this.intersections(ray, scene); if(isect != null) { return isect.dist; } else { return undefined; } }; RayTracer.prototype.traceRay = function(ray, scene, depth) { var isect = this.intersections(ray, scene); if(isect === undefined) { return Color.background; } else { return this.shade(isect, scene, depth); } }; RayTracer.prototype.shade = function(isect, scene, depth) { var d = isect.ray.dir; var pos = Vector.plus(Vector.times(isect.dist, d), isect.ray.start); var normal = isect.thing.normal(pos); var reflectDir = Vector.minus(d, Vector.times(2, Vector.times(Vector.dot(normal, d), normal))); var naturalColor = Color.plus(Color.background, this.getNaturalColor(isect.thing, pos, normal, reflectDir, scene)); var reflectedColor = (depth >= this.maxDepth) ? Color.grey : this.getReflectionColor(isect.thing, pos, normal, reflectDir, scene, depth); return Color.plus(naturalColor, reflectedColor); }; RayTracer.prototype.getReflectionColor = function(thing, pos, normal, rd, scene, depth) { return Color.scale(thing.surface.reflect(pos), this.traceRay({ start: pos, dir: rd }, scene, depth + 1)); }; RayTracer.prototype.getNaturalColor = function(thing, pos, norm, rd, scene) { var _this = this; var addLight = function(col, light) { var ldis = Vector.minus(light.pos, pos); var livec = Vector.norm(ldis); var neatIsect = _this.testRay({ start: pos, dir: livec }, scene); var isInShadow = (neatIsect === undefined) ? false : (neatIsect <= Vector.mag(ldis)); if(isInShadow) { return col; } else { var illum = Vector.dot(livec, norm); var lcolor = (illum > 0) ? Color.scale(illum, light.color) : Color.defaultColor; var specular = Vector.dot(livec, Vector.norm(rd)); var scolor = (specular > 0) ? Color.scale(Math.pow(specular, thing.surface.roughness), light.color) : Color.defaultColor; return Color.plus(col, Color.plus(Color.times(thing.surface.diffuse(pos), lcolor), Color.times(thing.surface.specular(pos), scolor))); } }; return scene.lights.reduce(addLight, Color.defaultColor); }; RayTracer.prototype.render = function(scene, ctx, screenWidth, screenHeight) { var getPoint = function(x, y, camera) { var recenterX = function(x) { return(x - (screenWidth / 2.0)) / 2.0 / screenWidth; }; var recenterY = function(y) { return -(y - (screenHeight / 2.0)) / 2.0 / screenHeight; }; return Vector.norm(Vector.plus(camera.forward, Vector.plus(Vector.times(recenterX(x), camera.right), Vector.times(recenterY(y), camera.up)))); }; for(var y = 0; y < screenHeight; y++) { for(var x = 0; x < screenWidth; x++) { var color = this.traceRay({ start: scene.camera.pos, dir: getPoint(x, y, scene.camera) }, scene, 0); var c = Color.toDrawingColor(color); ctx.fillStyle = "rgb(" + String(c.r) + ", " + String(c.g) + ", " + String(c.b) + ")"; ctx.fillRect(x, y, x + 1, y + 1); } } }; return RayTracer; }()); function defaultScene() { return { things: [new Plane(new Vector(0.0, 1.0, 0.0), 0.0, Surfaces.checkerboard), new Sphere(new Vector(0.0, 1.0, -0.25), 1.0, Surfaces.shiny), new Sphere(new Vector(-1.0, 0.5, 1.5), 0.5, Surfaces.shiny) ], lights: [{ pos: new Vector(-2.0, 2.5, 0.0), color: new Color(0.49, 0.07, 0.07) }, { pos: new Vector(1.5, 2.5, 1.5), color: new Color(0.07, 0.07, 0.49) }, { pos: new Vector(1.5, 2.5, -1.5), color: new Color(0.07, 0.49, 0.071) }, { pos: new Vector(0.0, 3.5, 0.0), color: new Color(0.21, 0.21, 0.35) }], camera: new Camera(new Vector(3.0, 2.0, 4.0), new Vector(-1.0, 0.5, 0.0)) }; } function exec() { var canv = document.createElement("canvas"); canv.width = 600; canv.height = 600; document.body.appendChild(canv); var ctx = canv.getContext("2d"); var rayTracer = new RayTracer(); return rayTracer.render(defaultScene(), ctx, canv.width, canv.height); } exec();
運行效果:
它是一種由ECMA國際(前身爲歐洲計算機制造商協會)制定和發佈的腳本語言規範,javascript在它基礎上經行了本身的封裝。但一般來講,術語ECMAScript和javascript指的是同一個。業界所說的ECMAScript實際上是指一種規範,或者說是一個標準。具體點來講,它其實就是一份文檔
JS包含三個部分:ECMAScript(核心)、DOM(文檔對象模型)、BOM(瀏覽器對象模型),ECMAScript是js語言的基礎。
(1) ECMAScript3
新增了對正則表達式、新控制語句、try-catch異常處理的支持,修改了字符處理、錯誤定義和數值輸出等內容。標誌着ECMAScript成爲了一門真正的編程語言。
(2) 第四版於2008年7月發佈前被廢棄。
(3)ECMAScript5
力求澄清第3版中的歧義,並添加了新的功能。新功能包括:原生JSON對象、繼承的方法、高級屬性的定義以及引入嚴格模式。
(4) ECMAScript6
是繼ES5以後的一次主要改進,增添了許多必要的特性,例如:模塊和類以及一些實用特性,Maps、Sets、Promises、生成器(Generators)等。
瀏覽器支持:
通常來講,除了針對個別特性的特殊說明,各大主流瀏覽器都支持es5,包括
其中IE9不支持es的嚴格模式,從IE10開始支持。Safari 5.1不支持 Function.prototype.bind
IE8只支持defineProperty
、getOwnPropertyDescriptor
的部分特性和JSon的新特性,IE9支持除了嚴格模式之外的新特性,IE10和其餘主流瀏覽器都支持了。
所以在PC端開發的時候,要注意IE9如下的兼容,移動端開發時,能夠比較放心了。
版本:
1995年,網景瀏覽器發佈,包含一種腳本語言叫LiveScript
1996年,網景爲搭上熱炒Java的順風車,將LiveScript更名爲Javascript, 並提供給ECMA International進行標準化
1997年,ECMAScript1發佈
1998年,ECMAScript2發佈
1999年,ECMAScript3發佈
3.0版是一個巨大的成功,在業界獲得普遍支持,成爲通行標準,奠基了JavaScript語言的基本語法,之後的版本徹底繼承。直到今天,初學者一開始學習JavaScript,其實就是在學3.0版的語法。
2007年,ECMAScript4.0版草案發布,原本預計次年8月發佈正式版本。可是,各方對因而否經過這個標準,發生了嚴重分歧。以Yahoo、Microsoft、Google爲首的大公司,反對JavaScript的大幅升級,主張小幅改動;以JavaScript創造者Brendan Eich爲首的Mozilla公司,則堅持當前的草案。
2008年, 因爲對於下一個版本應該包括哪些功能,各方分歧太大,爭論過於激烈,ECMA開會決定,停止ECMAScript 4.0的開發,將其中涉及現有功能改善的一小部分,發佈爲ECMAScript 3.1,而將其餘激進的設想擴大範圍,放入之後的版本,因爲會議的氣氛,該版本的項目代號起名爲Harmony(和諧)。會後不久,ECMAScript 3.1就更名爲ECMAScript 5。
2009年,ECMAScript5發佈,Harmony項目則一分爲二,一些較爲可行的設想定名爲JavaScript.next繼續開發,後來演變成ECMAScript 6;一些不是很成熟的設想,則被視爲JavaScript.next.next,在更遠的未來再考慮推出。TC39委員會的整體考慮是,ES5與ES3基本保持兼容,較大的語法修正和新功能加入,將由JavaScript.next完成。當時,JavaScript.next指的是ES6,第六版發佈之後,就指ES7。TC39的判斷是,ES5會在2013年的年中成爲JavaScript開發的主流標準,並在此後五年中一直保持這個位置。
2011年,ECMAScript5.1發佈
2015年,ECMAScript6發佈,同年決定之後將多年一次的完整的新版本發佈改成一年一次的新特性版本的發佈,所以ES6又叫ES2015
2017年,ECMAScript8(EcmaScript 2017)在6月底由TC39正式發佈
coffeescript已通過去了,除非你對它很是熟悉,不然建選擇typescript。
由於ECMAScript6的出現,javascript比之前要完善一些,但瀏覽器的支持度仍是不夠,可是有一天當JavaScript變得足夠完善時這些中間語言就沒有太多市場了。
上面提到的4種預處理工具均可以加快開發速度,某些程度上能夠提升代碼質量。
至於學習的方法我認爲官網有詳細的幫助。
總的來講要選擇:Coffeescript、TypeScript或ES6都有爭議。
https://git.coding.net/zhangguo5/CSS301.git
https://github.com/zhangguo5/CSS3_7.git
https://www.bilibili.com/video/av16530230/
9.一、請使用Sass與Less做爲CSS的中間語言完成以下頁面佈局。
9.二、要求將Sass與Less根據不一樣的主色調與輔助色生成出不一樣的樣式表,至少5個
9.三、在頁面頂部實現更換顏色的按鈕,點擊時切換CSS樣式表
參考網站:http://www.peise.net/tools/web/
切換樣式的參考代碼:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title></title> </head> <body> <h1>Hello Sass!</h1> <button type="button" class="color" data-color="css/red.css">紅色</button> <button type="button" class="color" data-color="css/blue.css">藍色</button> <link rel="stylesheet" type="text/css" href="#" id="css1"/> <script src="http://libs.baidu.com/jquery/2.0.0/jquery.min.js"></script> <script type="text/javascript"> $(".color").click(function(){ var file=$(this).data("color"); $("#css1").attr("href",file); }); </script> </body> </html>