Web全栈开发学习笔记—Part1 React入门—b.JavaScript

 

目录

JavaScript

Variables

Arrays

Objects

Functions

Object methods and "this"

Classes


JavaScript

JavaScript 在过去的几年里发展非常迅速,其标准的正式名称是ECMAScript。 

浏览器还不能支持所有 JavaScript 的最新特性,许多在浏览器中运行的代码需要从一个新版本的 JavaScript 转译到了一个更旧、更兼容的版本。

现在最流行的转译方法是使用 Babel。 在使用 create-React-app 创建的 React 应用中转译是自动配置好的。

Node.js是一个基于谷歌的 chrome V8 引擎的 JavaScript 运行时环境,可以在任何地方工作,从服务端到移动端。 代码文件以 .js结尾,通过 node 文件名.js 命令以运行文件。

还可以将 JavaScript 代码编写到 Node.js 控制台(通过在命令行中键入 node 打开),或者浏览器的开发工具控制台中。 最新版本的 Chrome 能 很好地 处理 JavaScript 的新特性,而且不需要转译代码。作为替代品,也可以选择 JS Bin这样的工具。

Variables

【变量】

在 JavaScript 中有以下几种定义变量的方法:

const x = 1
let y = 5

console.log(x, y)   // 1, 5 are printed
y += 10
console.log(x, y)   // 1, 15 are printed
y = 'sometext'
console.log(x, y)   // 1, sometext are printed
x = 4               // causes an error

const实际上并没有定义一个变量,而是定义了一个常量,也就是其值不能再更改了。 相对应的,let定义了一个普通变量。

在示例中可以看到,分配给变量的数据类型,在执行过程中可以发生更改。 例如开头的 y 存储了一个整数,但最后存储一个字符串。

也可以使用关键字var在 JavaScript 中定义变量。 在很长一段时间里,var 是定义变量的唯一方法。 const 和 let 是最近才在 ES6版本中添加的。 在一些特定情况,var 的工作方式与大多数语言中的变量定义相比是十分不同的。 推荐参考var, let and const - ES6 JavaScript Features

Arrays

【数组】

以下是数组和它的几个使用示例:

const t = [1, -1, 3]

t.push(5)

console.log(t.length) // 4 is printed
console.log(t[1])     // -1 is printed

t.forEach(value => {
  console.log(value)  // numbers 1, -1, 3, 5 are printed, each to own line
})                    

在这个示例中值得注意的是,即使将数组用 const 定义,也可以修改该数组中的内容。 因为数组是一个对象,而数组变量总是指向这同一个对象。 当添加新的元素时,数组的内容也将发生变化。

遍历元素的一种方法是使用 forEach ,如示例中所示, forEach 接收一个函数作为入参,这个函数用到了箭头语法。

value => {
  console.log(value)
}

forEach 为数组中的每个元素调用了这个函数,并总是将这单个项作为参数传递。 作为 forEach 的入参函数,也可以接收一些其他参数

在前面的示例中,使用了push方法将一个新元素添加到数组中。 在使用 React 时,经常使用函数式编程的技巧。 函数编程范型的一个特点,就是使用不可变的数据结构。 在React代码中,最好使用concat方法 ,因为它不向数组中添加元素,而是创建一个新数组,新数组中包含了旧数组和新的元素。

const t = [1, -1, 3]

const t2 = t.concat(5)

console.log(t)  // [1, -1, 3] is printed
console.log(t2) // [1, -1, 3, 5] is printed

t.concat(5) 这种方法调用不会向旧数组添加新的元素,而是直接返回一个新数组,该数组除了包含旧数组的元素外,还包含新的元素。

数组中定义了许多有用的方法,map方法的简短示例。

const t = [1, 2, 3]

const m1 = t.map(value => value * 2)
console.log(m1)   // [2, 4, 6] is printed

基于旧的数组,map 创建一个 新的数组,旧数组的每一项作为函数的入参来创建新的元素。 在这个例子中,就是旧数组的元素乘以2。

Map 还可以将数组转换为完全不同的内容:

const m2 = t.map(value => '<li>' + value + '</li>')
console.log(m2)  
// [ '<li>1</li>', '<li>2</li>', '<li>3</li>' ] is printed

这个例子使用 map 方法将整数值的数组转换为了包含 HTML 字符串的数组。 

数组中的单个元素可以很容易地通过解构赋值赋给变量。

const t = [1, 2, 3, 4, 5]

const [first, second, ...rest] = t

console.log(first, second)  // 1, 2 is printed
console.log(rest)          // [3, 4 ,5] is printed

由于这种解构赋值方式,变量 first 和 second 将接收数组的前两个整数作为它们的值。 剩余的整数被“收集”到另一个数组中,然后分配给变量 rest。

Objects

【对象】

在 JavaScript 中,定义对象有几种不同的方式。 一个非常常见的方法是使用对象字面量 ,就是通过在大括号中列出它的属性来实现的:

const object1 = {
  name: 'Arto Hellas',
  age: 35,
  education: 'PhD',
}

const object2 = {
  name: 'Full Stack web application development',
  level: 'intermediate studies',
  size: 5,
}

const object3 = {
  name: {
    first: 'Dan',
    last: 'Abramov',
  },
  grades: [2, 3, 5, 3],
  department: 'Stanford University',
}

属性的值可以是任何类型的,比如整数、字符串、数组、对象...。

对象的属性可以使用“句点”号或括号进行引用:

console.log(object1.name)         // Arto Hellas is printed
const fieldName = 'age' 
console.log(object1[fieldName])    // 35 is printed

也可以使用句点符号或括号来动态地往对象中添加属性:

object1.address = 'Helsinki'
object1['secret number'] = 12341

后面的那个属性的添加必须通过使用中括号来完成,因为在使用点符号的话,带空格的secret number并不是一个合法的属性名。

JavaScript 中的对象也可以包含方法。对象也可以使用所谓的构造函数来定义,这产生了一种类似其他编程语言的机制,例如 Java 中的类。 尽管有相似之处,JavaScript 并没有对标面向对象程序设计语言中类的概念。 但是,从 ES6版本开始,增加了类语法,这在某些情况下有助于构造面向对象的类。

Functions

【函数】

 定义箭头函数的完整过程如下:

const sum = (p1, p2) => {
  console.log(p1)
  console.log(p2)
  return p1 + p2
}

这个函数可以被如下方式调用:

const result = sum(1, 5)
console.log(result)

如果只有一个参数,我们可以在定义中去掉括号:

const square = p => {
  console.log(p)
  return p * p
}

如果函数只包含一个表达式,则不需要写大括号。 在这种情况下,函数只返回这个唯一表达式的结果。 现在,如果我们去掉控制台打印,可以进一步缩短函数定义如下:

const square = p => p * p

这种方式在操作数组时特别方便,例如,使用 map 方法:

const t = [1, 2, 3]
const tSquared = t.map(p => p * p)
// tSquared is now [1, 4, 9]

这个箭头函数是几年前随 ES6 一起添加到 JavaScript 中。 在此之前,定义函数的唯一方法是使用关键字 function

有两种方法可定义函数function; 一种是在函数声明中给一个名字。

function product(a, b) {
  return a * b
}

const result = product(2, 6)
// result is now 12

另一种定义函数的方法是使用函数表达式。 在这种情况下,没有必要为函数命名,定义可以放在代码的其它位置:

const average = function(a, b) {
  return (a + b) / 2
}

const result = average(2, 5)
// result is now 3.5

Object methods and "this"

【对象方法以及“ this”关键字】

箭头函数和使用function关键字的函数,在涉及到 this 关键字(指向对象本身)的行为上,有很大的不同。

我们可以通过给一个对象定义函数属性,来给对象分配方法:

const arto = {
  name: 'Arto Hellas',
  age: 35,
  education: 'PhD',
  greet: function() {    console.log('hello, my name is ' + this.name)  },}

arto.greet()  // "hello, my name is Arto Hellas" gets printed

方法甚至可以在对象创建之后再赋值给对象:

const arto = {
  name: 'Arto Hellas',
  age: 35,
  education: 'PhD',
  greet: function() {
    console.log('hello, my name is ' + this.name)
  },
}

arto.growOlder = function() {  this.age += 1}
console.log(arto.age)   // 35 is printed
arto.growOlder()
console.log(arto.age)   // 36 is printed

让我们稍微修改一下对象

const arto = {
  name: 'Arto Hellas',
  age: 35,
  education: 'PhD',
  greet: function() {
    console.log('hello, my name is ' + this.name)
  },
  doAddition: function(a, b) {    console.log(a + b)  },}

arto.doAddition(1, 4)        // 5 is printed

const referenceToAddition = arto.doAddition
referenceToAddition(10, 15)   // 25 is printed

现在对象有了 doAddition 方法,该方法将传递给他的参数进行求和。 该方法通常使用对象的 arto.doAddition(1, 4) 来调用,或者通过赋值给变量的 方法引用  ,referenceToAddition(10, 15)来调用该方法

如果我们用同样的方式调用greet函数,我们就会遇到一个问题:

arto.greet()       // "hello, my name is Arto Hellas" gets printed

const referenceToGreet = arto.greet
referenceToGreet() // prints "hello, my name is undefined"

当通过引用调用referenceToGreet() 方法时,该方法已经不认识原始的this是什么了。 与其他语言相反,在 JavaScript 中,this的值是根据 方法如何调用 来定义的。 当通过引用调用该方法时, this 的值就变成了所谓的全局对象 ,而最终结果往往不是软件开发者设想的那样。

失去对this 关键字的追踪,在编写 JavaScript 代码时会带来一些潜在的问题。 通常情况下,React 或 Node (或者更确切地说是 web 浏览器的 JavaScript 引擎) 需要调用开发人员定义的对象中的某个方法。 然而,在本课程中,我们会使用“ 去this” (避免使用this关键字)的JavaScript 来避免这些问题。

例如,当我们使用setTimeout方法,让arto对象1秒钟后调用greet。

const arto = {
  name: 'Arto Hellas',
  greet: function() {
    console.log('hello, my name is ' + this.name)
  },
}

setTimeout(arto.greet, 1000)

如上所述,在 JavaScript 中,this 的值是根据方法的调用方式来定义的。 当 setTimeout 调用该方法时,实际上是JavaScript引擎在调用该方法,此时的this是指向的是全局对象。

有几种机制可以保留这种原始的 this 。 其中一个是使用bind方法:

setTimeout(arto.greet.bind(arto), 1000)

调用 arto.greet.bind(arto) 创建了一个新函数,它将 this 绑定指向到了 Arto,这与方法的调用位置和方式无关。

使用箭头函数可以解决与 this相关的一系列问题, 但是它不能当做对象的方法来使用。

Classes

【类】

正如前面提到的,JavaScript 中并没有像面向对象程序语言中的类机制。 然而,JavaScript 中的一些新特性使得它能够“模拟”面向对象中的

与 ES6一起引入到 JavaScript 中的类语法,在很大程度上简化了 JavaScript 中的类(或者说像是类)的定义。

下面的代码,定义了一个名为 Person 的“类”和两个 Person 对象。

class Person {
  constructor(name, age) {
    this.name = name
    this.age = age
  }
  greet() {
    console.log('hello, my name is ' + this.name)
  }
}

const adam = new Person('Adam Ondra', 35)
adam.greet()

const janja = new Person('Janja Garnbret', 22)
janja.greet()

在语法方面,类以及由它们创建的对象非常类似于 Java 的类和对象。 它们的行为也非常类似于 Java 对象。 但在本质上,它们仍然是基于 JavaScript 的原型继承的对象。 这两个对象的类型实际上都是 Object,因为 JavaScript 实质上只定义了Boolean,Null,Undefined,Number,String,Symbol,BigInt,以及 Object几种类型。

猜你喜欢

转载自blog.csdn.net/qq_39389123/article/details/111351648