freeCodeCamp 旅途5 - JavaScript 和 ES6

JavaScript 基础

JavaScript 是一门所有现代 Web 浏览器都支持的高级编程语言。
JavaScript 中的注释方式有以下两种:

  • 使用//注释掉当前行的代码,// 这是一条单行注释。
  • 使用多行注释来注释你的代码,以/开始,用/来结束,/* 这是一个多行注释 */

变量

1、变量的定义
在计算机科学中,数据就是一切,它对于计算机意义重大。JavaScript 提供七种不同的数据类型,它们是undefined(未定义), null(空),boolean(布尔型),string(字符串),symbol(符号),number(数字),和object(对象)。
变量 允许计算机以一种动态的形式来存储和操作数据,通过操作指向数据的指针而不是数据本身来避免了内存泄露,以上的七种数据类型都可以存储到一个变量中。

通过在变量的前面使用关键字var,声明一个变量:var ourName; ,创建一个名为ourName变量,在 JavaScript 中我们以分号结束语句。

变量名称可以由数字、字母、美元符号$ 或者 下划线_组成,但是不能包含空格或者以数字为开头。好的变量名,见名知义,如: var myName;

在 JavaScript 中所有的变量和函数名都是大小写敏感的。要区别对待大写字母和小写字母。MYVARMyVarmyvar是截然不同的变量。
使用驼峰命名法来书写一个 Javascript 变量,在驼峰命名法中,变量名的第一个单词的首写字母小写,后面的单词的第一个字母大写。如:var someVariable; var anotherVariableName;

2、变量的赋值
在 JavaScript 中,你可以使用赋值运算符将值存储在变量中。
myVariable = 5; ,这条语句把Number类型的值5赋给变量myVariable

赋值过程是从右到左进行的。在将值分配给运算符左侧的变量之前,将解析=运算符右侧的所有内容。

myVar = 5;  // 数值5被赋给变量myVar中,没有 var 声明的变量的全局变量
myNum = myVar;  //  将变量myVar解析为5并将其赋给myNum变量

通常在声明变量的时候会给变量初始化一个初始值。

var myVar = 0;  //  创建一个名为 myVar 的变量并指定一个初始值0。

3、undefined 未初始化的变量
当 JavaScript 中的变量被声明的时候,程序内部会给它一个初始值undefined。当你对一个值为undefined的变量进行运算操作的时候,算出来的结果将会是NaNNaN的意思是"Not a Number"。当你用一个值是undefined的变量来做字符串拼接操作的时候,它会输出字符串"undefined"

var a;      a = a + 1;     console.log(a);  //  NaN
var b;      b = b + 5;     console.log(b);  //  NaN
var c;      c = c + " String!";     console.log(c);  //  undefined String!

运算符

运算符 含义 实例
+、-、*、/、% 加、减、乘、除、取余,算数运算符 myVar = 5 + 10; myDecimal = 2.0 * 2.5;
i++、++i、i--、--i 自增、自减,等价于 i=i+1、i=i-1,但 i++ 先运算输出再加1,++i 是先加1再做运算 var myVar = 87;myVar++; 等价于 var myVar = 87;myVar = myVar + 1;
=、+=、-=、*=、/=、%= 赋值、复合赋值 myVar = myVar + 5; 等价于 myVar += 5;
&&、 、! 与、或、非,逻辑运算符 !false
==、===、!=、!==、>、<、>=、<= 等于、全等、不等、全不等、大于、小于、大于等于、小于等于 x=5; x==8 为 false
? : 三元运算符 condition ? statement-if-true : statement-if-false;

数据类型

在JavaScript中,你可以使用typeof运算符确定变量的类型或值,typeof 3 // 返回 'number' 。
简单数据类型:

  • number :整数(-1,0,1)、浮点数(-1.1,1.1)

  • stirng :用单引号或双引号包裹着,var myName = "Daenerys Targaryen";

    • 字符串有特殊字符需要使用反斜杠(\)转义,var sampleStr = "Alan said, "Peter is learning JavaScript".";
    • 使用单引号包裹双引号或者相反,conversation = 'Finn exclaims to Jake, "Algebraic!"';
    • 字符串中的转义序列:' 、" 、\ 、\n 、\r 、\t 、\b(退格) 、\f (换页符)
    • 用加号连接字符串,var myVar = 'My name is Alan,' + ' I concatenate.'
    • 在字符串变量或字符串后面写上.length来获得字符串变量字符串值的长度,lastNameLength = lastName.length;
    • 方括号获取在字符串中的特定index(索引)处获取字符,firstLetterOfLastName = lastName[0];
  • array :以左方括号[开始定义一个数组,以右方括号]结束,里面每个元素之间用逗号隔开,var myArray = ["dragon", 22];

    • 数组的嵌套:var myArray = [["Game of Thrones", 8], ["golden state warriors", 4]];
    • 通过索引访问数组中的数据:var myData = myArray[0];
    • push:追加到最后, myArray.push(["dog", 3]);
    • pop:抛出最后的,var removedFromMyArray = myArray.pop();
    • shift:移除第一项,var removedFromMyArray = myArray.shift();
    • unshift:添加到第一项,myArray.unshift(["Paul", 35]);
  • boolean:布尔,布尔值要么是 true 要么是 false

  • object:对象

    • 对象和数组很相似,数组是通过索引来访问和修改数据,而对象是通过属性来访问和修改数据。
    • 对象适合用来存储结构化数据,var cat = { "name": "Whiskers", "legs": 4, "tails": 1, "enemies": ["Water", "Dogs"] };
    • 有两种方式访问对象属性,一个是点操作符(.),一个是中括号操作符([])。
    • 删除对象的属性:delete ourDog.bark;
    • 测试对象的属性:myObj.hasOwnProperty("top"); 返回 true 或者 false
    • JavaScript 对象是处理灵活数据的一种方法。它可以储存字符串,数字,布尔值,函数,和对象以及这些值的任意组合。
    • JavaScript Object Notation 简称JSON是用于存储数据的相关数据交换格式。
    • 数组中有多个 JSON 对象的时候,对象与对象之间要用逗号隔开。

函数

在 JavaScript 中,我们可以把代码的重复部分抽取出来,放到一个函数中。

函数的参数parameters在函数中充当占位符(也叫形参)的作用,参数可以为一个或多个。调用一个函数时所传入的参数为实参,实参决定着形参真正的值。简单理解:形参即形式、实参即内容。

function reusableFunction() {
    console.log("Hi World");
}     //  定义一个函数
reusableFunction();  //  使用函数名调用

function testFun(param1, param2) {
  console.log(param1, param2);
}     //  接收两个参数的函数
testFun("Hello", "World");  //  函数中,param1等于“Hello”,param2等于“World”

function processArg(num) {
  return (num + 3) / 5;
}    //  使用 return  返回函数结果,没有 return 返回的值时 undefined

作用域

在 JavaScript 中,作用域涉及到变量的作用范围。在函数外定义的变量具有 全局 作用域。这意味着,具有全局作用域的变量可以在代码的任何地方被调用。

没有使用var关键字定义的变量,会被自动创建在全局作用域中,形成全局变量。当在代码其他地方无意间定义了一个变量,刚好变量名与全局变量相同,这时会产生意想不到的后果。因此你应该总是使用var关键字来声明你的变量。

在一个函数内声明的变量,以及该函数的参数都是局部变量,意味着它们只在该函数内可见。

一个程序中有可能具有相同名称的局部变量全局变量。在这种情况下,局部变量将会优先于全局变量。

内置函数

Math.random()用来生成一个在0(包括 0)到1(不包括 1)之间的随机小数,因此Math.random()可能返回 0 但绝不会返回 1。
Math.floor()向下取整 获得它最近的整数,Math.floor(Math.random() * (myMax - myMin + 1)) + myMin;
parseInt()函数解析一个字符串返回一个整数,var a = parseInt("007");

流程控制

1、用 if 语句来表达条件逻辑

if (val > 5) {
    result = "Bigger than 5";
 }        //   if  ...

if (num > 10) {
  return "Bigger than 10";
} else {
  return "10 or Less";
}        //   if ...  else ...

if (num > 15) {
return "Bigger than 15";
} else if (num < 5) {
return "Smaller than 5";
} else {
return "Between 5 and 15";
}     //   if  ...  else if ...  else

2、使用 Switch 语句从许多选项中进行选择,case 中执行的是严格相等===

switch (num) {
  case value1:
    statement1;
    break;
  case value2:
    statement2;
    break;
...
  default:
    defaultStatement;
    break;
}

3、while 循环

var ourArray = [];
var i = 0;
while(i < 5) {
  ourArray.push(i);
  i++;
}

4、for 循环,for ([初始化]; [条件判断]; [计数器])

var ourArray = [];
for (var i = 0; i < 5; i++) {
  ourArray.push(i);
}
var arr = [10,9,8,7,6];
for (var i = 0; i < arr.length; i++) {
   console.log(arr[i]);
}
var arr = [  [1,2], [3,4], [5,6] ];
for (var i=0; i < arr.length; i++) {
  for (var j=0; j < arr[i].length; j++) {
    console.log(arr[i][j]);
  }
}

5、do...while 循环,它会先执行do里面的代码,如果while表达式为真则重复执行,反之则停止执行。

var ourArray = [];
var i = 0;
do {
  ourArray.push(i);
  i++;
} while (i < 5);

ES6

ECMAScript 是 JavaScript 的标准化版本,它旨在统一语言语言的规范和功能。所有主流的浏览器或者 Javascript 的运行环境都支持这个规范,因此 ECMAScriptJavaScript 的术语是通用的。在2015年,ECMAScript 发布了被称为 ECMAScript 6 (ES6) 的最新版本。

var 和 let 关键字之间的差异

使用var关键字来声明变量,会出现重复声明导致变量被覆盖却不会报错的问题:

var camper = 'James';
var camper = 'David';
console.log(camper);   // 打印出 'David'

在 ES6 中引入了新的关键字let来解决var关键字带来的潜在问题。如果你在上面的代码中,使用了let关键字来代替var关键字,结果会是一个报错。

let camper = 'James';
let camper = 'David'; // 报错  Uncaught SyntaxError:...has already been declared

请注意"use strict"。这代表着开启了严格模式,用于检测常见的代码错误以及"不安全"的行为,例如:"use strict"; x = 3.14; // x 没有声明导致了报错

当你使用var关键字来声明一个变量的时候,这个变量会被声明成全局变量,或是函数内的局部变量。
let关键字的作用类似,但会有一些额外的特性。如果你在代码块、语句或表达式中使用关键字let声明变量,这个变量的作用域就被限制在当前的代码块,语句或表达式之中。

var numArray = [];
for (var i = 0; i < 3; i++) {
  numArray.push(i);
}   //  当使用var关键字的时候,i会被声明成全局变量。当i++执行的时候,它会改变全局变量的值。
console.log(numArray);   // 返回 [0, 1, 2]
console.log(i);   // 返回 3

var printNumTwo;
for (var i = 0; i < 3; i++) {
  if(i === 2){
    printNumTwo = function() {  return i;    };
  }
}  // i 发生了改变,函数printNumTwo()返回的是全局变量i的值,不是for循环中创建函数时 i 的值
console.log(printNumTwo());    // 返回 3

'use strict';
let printNumTwo;
for (let i = 0; i < 3; i++) {
  if (i === 2) {
    printNumTwo = function() {      return i;    };
  }  //  i在全局作用域中没有声明,所以它没有被定义,它的声明只会发生在for循环内
}
console.log(printNumTwo());   // 返回 2
console.log(i);   // 返回 "没有定义 i 变量"

用 const 关键字声明只读变量

let并不是唯一的新的声明变量的方式。在 ES6 里面,你还可以使用const关键字来声明变量。
const拥有let的所有优点,所不同的是,通过const声明的变量是只读的。这意味着通过const声明的变量只能被赋值一次,而不能被再次赋值。

"use strict"
const FAV_PET = "Cats";
FAV_PET = "Dogs"; // 报错 Uncaught TypeError: Assignment to constant variable.

对象(包括数组和函数)在使用const声明的时候依然是可变的。使用const来声明只会保证它的标识不会被重新赋值。

"use strict";
const s = [5, 6, 7];
s = [1, 2, 3];  // 试图给 const 变量赋值,报错
s[2] = 45;  // 与用 var 或 let 声明的数组一样,这个操作也会成功
console.log(s); // 返回 [5, 6, 45]

防止对象改变const声明并不会真的保护你的数据不被改变。为了确保数据不被改变,JavaScript 提供了一个函数Object.freeze来防止数据改变。
当一个对象被冻结的时候,你不能再对它的属性再进行增、删、改的操作。任何试图改变对象的操作都会被阻止,却不会报错。

let obj = {
  name:"FreeCodeCamp",
  review:"Awesome"
};
Object.freeze(obj);
obj.review = "bad"; // obj 对象被冻结了,这个操作会被忽略
obj.newProp = "Test"; // 也会被忽略,不允许数据改变
console.log(obj);   // { name: "FreeCodeCamp", review:"Awesome"}

使用箭头函数编写简洁的匿名函数

在 JavaScript 里,我们会经常遇到不需要给函数命名的情况,尤其是在需要将一个函数作为参数传给另外一个函数的时候。通常会使用以下语法:

const myFunc = function() {
  const myVar = "value";
  return myVar;
}

ES6 提供了其他写匿名函数的方式的语法糖。你可以使用箭头函数:

const myFunc = () => {
  const myVar = "value";
  return myVar;
}

当不需要函数体,只返回一个值的时候,箭头函数允许你省略return关键字和外面的大括号。

const myFunc= () => "value"    //   这段代码仍然会返回value。

编写带参数的箭头函数:

const doubler = (item) => item * 2;  // 给传入的数值乘以 2 并返回结果

编写高阶箭头函数:箭头函数在类似map()filter()reduce()等需要其他函数作为参数来处理数据的高阶函数里会很好用。

const realNumberArray = [4, 5.6, -9.8, 3.14, 42, 6, 8.34];
const squareList = (arr) => {
  "use strict";
  const squaredIntegers = (arr.filter((cur) =>  cur > 0 && cur % 1 == 0)).map((cur) => Math.pow(cur,2));   // 计算 squaredIntegers 数组里正整数的平方
  return squaredIntegers;
};
const squaredIntegers = squareList(realNumberArray);
console.log(squaredIntegers);   //  [16, 1764, 36]

设置函数的默认参数:ES6 里允许给函数传入默认参数,来构建更加灵活的函数。

function greeting(name = "Anonymous") {
  return "Hello " + name;
}
console.log(greeting("John")); // Hello John
console.log(greeting()); // Hello Anonymous

将 rest 操作符与函数参数一起使用,在rest操作符的帮助下,你可以创建有一个变量来接受多个参数的函数。这些参数被储存在一个可以在函数内部读取的数组中。

function howMany(...args) {
  return "You have passed " + args.length + " arguments.";
}
console.log(howMany(0, 1, 2)); // 输出:You have passed 3 arguments.
console.log(howMany("string", null, [1, 2, 3], { })); // 输出:You have passed 4 arguments.

// rest操作符可以避免查看args数组的需求,并且允许我们在参数数组上使用map(),fiter(),和reduce()。

使用 spread 运算符展开数组项

var arr = [6, 89, 3, 45];    //   ES5 代码
var maximus = Math.max.apply(null, arr); // 返回 89
// 必须使用Math.max.apply(null,arr),是因为直接调用Math.max(arr)会返回NaN。
// Math.max()函数需要传入的是一系列由逗号分隔的参数,而不是一个数组。
// Function.apply()是JS的一个OOP特性,一般用来模拟继承和扩展this的用途
// XXX.apply是一个调用函数的方法,其参数为:apply(Function, Args),
// Function为要调用的方法,Args是参数列表,当Function为null时,默认为上文,

const arr = [6, 89, 3, 45];  //  ES6 代码
const maximus = Math.max(...arr); // 返回 89
//  ...arr返回了一个“打开”的数组。或者说它 展开 了数组。
//  展开操作符只能够在函数的参数中,或者数组之中使用
const spreaded = ...arr; // 将会发生语法错误

使用解构赋值从对象中分配变量

var voxel = {x: 3.6, y: 7.4, z: 6.54 };  //  ES5 代码
var x = voxel.x; // x = 3.6
var y = voxel.y; // y = 7.4
var z = voxel.z; // z = 6.54

const { x, y, z } = voxel; // x = 3.6, y = 7.4, z = 6.54  ES6 代码
const { x : a, y : b, z : c } = voxel;  // a = 3.6, b = 7.4, c = 6.54 将voxel.x,voxel.y,voxel.z的值分别赋给a,b,c,

//  使用解构赋值从嵌套对象中分配变量
const a = {
  start: { x: 5, y: 6},
  end: { x: 6, y: -9 }
};
const { start : { x: startX, y: startY }} = a;
console.log(startX, startY); // 5, 6

//  使用解构赋值从数组中分配变量
const [a, b,,, c] = [1, 2, 3, 4, 5, 6];
console.log(a, b, c); // 1, 2, 5

// 使用解构赋值配合 rest 操作符来重新分配数组元素
const [a, b, ...arr] = [1, 2, 3, 4, 5, 7];
console.log(a, b); // 1, 2
console.log(arr); // [3, 4, 5, 7]

// 使用解构赋值将对象作为函数的参数传递
const profileUpdate = (profileData) => {
  const { name, age, nationality, location } = profileData;  // 对这些变量执行某些操作
}
//  等价于
const profileUpdate = ({ name, age, nationality, location }) => {
  /* 对这些参数执行某些操作 */
}

使用模板字面量创建字符串

模板字符串是 ES6 的另外一项新的功能。这是一种可以轻松构建复杂字符串的方法。
使用的{variable}语法是一个占位符。当需要在字符串里增加变量的时候,你只需要在变量的外面括上{和},并将其放在字符串里就可以了。不再需要使用+运算符。
其次,在例子使用了反引号(`),而不是引号('或者")将字符串括了起来,并且这个字符串可以换行。

const person = {
  name: "Zodiac Hasbro",
  age: 56
};
const greeting = `Hello, my name is ${person.name}!
I am ${person.age} years old.`;
console.log(greeting); // Hello, my name is Zodiac Hasbro!   // I am 56 years old.

使用简单字段编写简洁的对象字面量声明:

const getMousePosition = (x, y) => ({
  x: x,
  y: y
});  //  返回拥有2个属性的对象的简单函数

// ES6 提供了一个语法糖,消除了类似`x: x`这种冗余的写法.你可以仅仅只写一次`x,解释器会自动将其转换成x: x`。
const getMousePosition = (x, y) => ({ x, y });

//  用 ES6 编写简洁的函数声明
const person = {
  name: "Taylor",
  sayHello() {
    return `Hello! My name is ${this.name}.`;
  }
};

使用 class 语法定义构造函数:

var SpaceShuttle = function(targetPlanet){
  this.targetPlanet = targetPlanet;
}  // ES5 构造函数写法
var zeus = new SpaceShuttle('Jupiter');

class SpaceShuttle {
  constructor(targetPlanet){
    this.targetPlanet = targetPlanet;
  }   // ES6 构造函数写法
}
const zeus = new SpaceShuttle('Jupiter');

使用 getter 和 setter 来控制对象的访问:

  • Getter 函数的作用是可以让返回一个对象私有变量的值给用户,而不需要直接去访问私有变量。
  • Setter 函数的作用是可以基于传进的参数来修改对象中私有变量的值。这些修改可以是计算,或者是直接替换之前的值。
class Book {
  constructor(author) {
    this._author = author;
  }
  // getter
  get writer(){
    return this._author;
  }
  // setter
  set writer(updatedAuthor){
    this._author = updatedAuthor;
  }
}
const lol = new Book('anonymous');
console.log(lol.writer);  // anonymous
lol.writer = 'wut';
console.log(lol.writer);  // wut

了解 import 和 require 之间的差异

在过去,我们会使用require()函数来从外部文件或模块中引入函数或者代码。这时候会遇到一个问题:有些文件或者模块会特别大,但你却往往只需要引入其中的一些核心代码。
ES6 给我们提供了import这个便利的工具。通过它,我们能够从外部的文件或者模块中选择我们需要的部分进行引入,从而节约载入的时间和内存空间。

想象math_array_functions拥有大概20个函数,但是我只需要countItems这一个函数在我当前的文件里。使用老的require()方式会强制我引入所有20个函数。而使用新的import语法,我可以只引入需要的那个函数:

import { countItems } from "math_array_functions" // 只引入需要的那个函数

import { function } from "file_path_goes_here"  // 我们还可以用同样的方式来引入变量!

在许多的例子中,在文件的路径前会加上./;否则, node.js 会先尝试去node_modules目录中寻找依赖项。

用 export 来重用代码块 :import语句是如何从大文件中引入其中的部分代码的。为了让其正常的工作,我们还必须了解一个与之相关的语句,叫做export。当我们想要一些代码——函数或者变量——在其他文件中使用,我们必须将它们导出来供其他文件导入。

const capitalizeString = (string) => {
  return string.charAt(0).toUpperCase() + string.slice(1);
}
export { capitalizeString } //如何导出函数。
export const foo = "bar"; //如何导出变量。
// 等价于
const foo = "bar";
export { capitalizeString, foo }  // 将你所有的export语句打包成一行

用 * 从文件中导入所有内容 :用import语法从文件中导入所有的内容。

import * as myMathModule from "math_functions";
myMathModule.add(2,3);
myMathModule.subtract(5,3);

用 export default 创建一个默认导出 :在文件中只有一个值需要导出的时候,你通常会使用这种语法。它也常常用于给文件或者模块创建返回值。
当使用export default去声明一个文件或者模块的返回值,你在每个文件或者模块中应当只默认导出一个值。特别地,你能将export deafultvarletconst一起使用。

export default function add(x,y) {
  return x + y;
}

导入一个默认的导出 :与导出值的方法不同,导入默认导出的写法仅仅只是简单的讲变量名写在import之后。

//  有一个add函数, 它在"math_functions"文件里默认被导出
import add from "math_functions";
add(5,4); //将会返回 9
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,222评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,455评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,720评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,568评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,696评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,879评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,028评论 3 409
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,773评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,220评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,550评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,697评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,360评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,002评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,782评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,010评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,433评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,587评论 2 350

推荐阅读更多精彩内容

  • 第一章 前端三大语言:HTML(专门编写网页内容)、CSS(编写网页样式)、JS(专门编写网页交互行为) 能简写尽...
    fastwe阅读 943评论 0 0
  • Comment your JavaScript Code JavaScript中的注释方式有以下两种: 使用 //...
    归云丶阅读 1,097评论 0 0
  • JavaScript 注释语句操作 注释的代码块在JavaScript之中是不会运行的。注释是一个非常好的方式让你...
    followyounger1阅读 7,946评论 0 2
  • 概要 64学时 3.5学分 章节安排 电子商务网站概况 HTML5+CSS3 JavaScript Node 电子...
    阿啊阿吖丁阅读 9,142评论 0 3
  • JavaScript简介 JavaScript是网景公司开发基于浏览器,基于面向对象,基于事件驱动式网页脚本语言 ...
    liusong007阅读 523评论 3 4