• Linear Algebra: Vectors
  • Rodion Chachura
  • The Nuggets translation Project
  • Permanent link to this article: github.com/xitu/gold-m…
  • Translator: lsvih
  • Proofread by: Endone

This article is part of the “JavaScript Linear Algebra” tutorial.

Vectors are methods used to accurately represent directions in space. A vector consists of a series of values, each of which is a component of the vector. In the figure below, you can see a vector with two components in two dimensions. In three dimensions, a vector is going to have three components.

We can create a Vector2D class for a 2-dimensional vector, and then a Vector3D class for a 3-dimensional vector. But there’s a problem with this: vectors aren’t just used to represent directions in physical space. For example, we might want to represent a color (RGBA) as a vector, which would have four components: red, green, blue, and alpha channels. Or, we can use vectors to represent n choices with different proportions (such as a vector representing the probability of each horse winning a race with 5 horses). Therefore, we create a class that does not specify a dimension and use it like this:

class Vector {
  constructor(... components) {this.components = components
  }
}

const direction2d = new Vector(1.2)
const direction3d = new Vector(1.2.3)
const color = new Vector(0.5.0.4.0.7.0.15)
const probabilities = new Vector(0.1.0.3.0.15.0.25.0.2)
Copy the code

Vector operations

Consider the case of two vectors, for which the following operations can be defined:

Where, α ∈ R is an arbitrary constant.

We visualized operations other than the cross product, and you can find examples here. The GitHub repository contains the React project and associated libraries for creating these visual examples. If you want to know how to make these 2d visualizations using React and SVG, please refer to this article.

Addition and subtraction

Similar to numerical operations, you can add and subtract vectors. When performing arithmetic operations on vectors, the results can be obtained by directly performing numerical operations on their respective components:

The addition function takes another vector as an argument, adds the corresponding vector components, and returns the resulting new vector. The subtraction function is similar, but replaces addition with subtraction:

class Vector {
  constructor(... components) {this.components = components
  }

  add({ components }) {
    return newVector( ... components.map((component, index) = > this.components[index] + component)
    )
  }
  subtract({ components }) {
    return newVector( ... components.map((component, index) = > this.components[index] - component)
    )
  }
}

const one = new Vector(2.3)
const other = new Vector(2.1)
console.log(one.add(other))
// Vector { components: [ 4, 4 ] }
console.log(one.subtract(other))
// Vector { components: [ 0, 2 ] }
Copy the code

The zoom

We can scale a vector to any value α ∈ R. When you scale, you multiply all the vector components by the scaling factor alpha. When α > 1, the vector becomes longer; When 0 is less than or equal to alpha is less than 1, the vector gets shorter. If alpha is negative, the scaled vector will point in the opposite direction of the original vector.

In the scaleBy method, we multiply all vector components by the value of the passed parameter to get the new vector and return:

class Vector {
  constructor(... components) {this.components = components
  }
  // ...

  scaleBy(number) {
    return newVector( ... this.components.map(component= > component * number)
    )
  }
}

const vector = new Vector(1.2)
console.log(vector.scaleBy(2))
// Vector { components: [ 2, 4 ] }
console.log(vector.scaleBy(0.5))
// Vector {components: [0.5, 1]}
console.log(vector.scaleBy(- 1))
// Vector { components: [ -1, -2 ] }
Copy the code

The length of the

Vector length can be derived from the Pythagorean theorem:

Since there are ready-made functions in the Math object built into JavaScript, calculating the length is simple:

class Vector {
  constructor(... components) {this.components = components
  }
  // ...
  
  length() {
    return Math.hypot(... this.components) } }const vector = new Vector(2.3)
console.log(vector.length())
/ / 3.6055512754639896
Copy the code

The dot product

The dot product will tell you how similar two vectors are. The dot product method takes two vectors as inputs and outputs a number. The dot product of two vectors is equal to the sum of the products of their corresponding components.

In dotProduct method, another vector is received as a parameter and the sum of products of corresponding components is calculated by reduce method:

class Vector {
  constructor(... components) {this.components = components
  }
  // ...
  
  dotProduct({ components }) {
    return components.reduce((acc, component, index) = > acc + component * this.components[index], 0)}}const one = new Vector(1.4)
const other = new Vector(2.2)
console.log(one.dotProduct(other))
/ / 10
Copy the code

Before we can look at the relationship between the directions of several vectors, we need to implement a method to normalize the length of a vector to one. This normalized vector is used in many scenarios. For example, when we need to specify a direction in space, we need a normalized vector to represent that direction.

class Vector {
  constructor(... components) {this.components = components
  }
  // ...
  
  normalize() {
    return this.scaleBy(1 / this.length())
  }
}

const vector = new Vector(2.4)
const normalized = vector.normalize()
console.log(normalized)
// Vector {components: [0.4472135954999579, 0.8944271909999159]}
console.log(normalized.length())
/ / 1
Copy the code

If the dot product of two normalized vectors is equal to 1, that means they’re going in the same direction. We created areEqual to compare two floating point numbers:

const EPSILON = 0.00000001

const areEqual = (one, other, epsilon = EPSILON) = >
  Math.abs(one - other) < epsilon

class Vector {
  constructor(... components) {this.components = components
  }
  // ...
  
  haveSameDirectionWith(other) {
    const dotProduct = this.normalize().dotProduct(other.normalize())
    return areEqual(dotProduct, 1)}}const one = new Vector(2.4)
const other = new Vector(4.8)
console.log(one.haveSameDirectionWith(other))
// true
Copy the code

If the dot product of two normalized vectors equals -1, they are in opposite directions:

class Vector {
  constructor(... components) {this.components = components
  }
  // ...
  haveOppositeDirectionTo(other) {
    const dotProduct = this.normalize().dotProduct(other.normalize())
    return areEqual(dotProduct, - 1)}}const one = new Vector(2.4)
const other = new Vector(4 -.- 8 -)
console.log(one.haveOppositeDirectionTo(other))
// true
Copy the code

If the dot product of two normalized vectors is 0, the two vectors are perpendicular to each other:

class Vector {
  constructor(... components) {this.components = components
  }
  // ...
  
  isPerpendicularTo(other) {
    const dotProduct = this.normalize().dotProduct(other.normalize())
    return areEqual(dotProduct, 0)}}const one = new Vector(2 -.2)
const other = new Vector(2.2)
console.log(one.isPerpendicularTo(other))
// true
Copy the code

Cross product

The cross product applies only to three-dimensional vectors and produces vectors perpendicular to the two input vectors:

When we implement the cross product, we assume that it’s only used to compute vectors in three dimensions.

class Vector {
  constructor(... components) {this.components = components
  }
  // ...
  
  // Applies only to 3-dimensional vectors
  crossProduct({ components }) {
    return new Vector(
      this.components[1] * components[2] - this.components[2] * components[1].this.components[2] * components[0] - this.components[0] * components[2].this.components[0] * components[1] - this.components[1] * components[0])}}const one = new Vector(2.1.1)
const other = new Vector(1.2.2)
console.log(one.crossProduct(other))
// Vector { components: [ 0, -3, 3 ] }
console.log(other.crossProduct(one))
// Vector { components: [ 0, 3, -3 ] }
Copy the code

Other common methods

In real life applications, the above methods are far from enough. For example, we sometimes need to find the Angle between two vectors, invert one vector, or calculate the projection of one vector onto another.

Before we start writing the above methods, we need to write the following two functions to convert between degrees and radians:

const toDegrees = radians= > (radians * 180) / Math.PI
const toRadians = degrees= > (degrees * Math.PI) / 180
Copy the code

The Angle

class Vector {
  constructor(... components) {this.components = components
  }
  // ...
  
  angleBetween(other) {
    return toDegrees(
      Math.acos(
        this.dotProduct(other) /
        (this.length() * other.length())
      )
    )
  }
}

const one = new Vector(0.4)
const other = new Vector(4.4)
console.log(one.angleBetween(other))
/ / 45.00000000000001
Copy the code

reverse

When we need to scale a vector in the opposite direction, we can scale the vector by -1:

class Vector {
  constructor(... components) {this.components = components
  }
  // ...
  
  negate() {
    return this.scaleBy(- 1)}}const vector = new Vector(2.2)
console.log(vector.negate())
// Vector { components: [ -2, -2 ] }
Copy the code

projection

class Vector {
  constructor(... components) {this.components = components
  }
  // ...
  
  projectOn(other) {
    const normalized = other.normalize()
    return normalized.scaleBy(this.dotProduct(normalized))
  }
}

const one = new Vector(8.4)
const other = new Vector(4.7)
console.log(other.projectOn(one))
// Vector { components: [ 6, 3 ] }
Copy the code

Set the length of the

When you need to specify a length for a vector, use the following method:

class Vector {
  constructor(... components) {this.components = components
  }
  // ...
  withLength(newLength) {
    return this.normalize().scaleBy(newLength)
  }
}

const one = new Vector(2.3)
console.log(one.length())
/ / 3.6055512754639896
const modified = one.withLength(10)
/ / 10
console.log(modified.length())
Copy the code

Judgment is equal

To determine whether two vectors areEqual, we can use the areEqual function for their corresponding components:

class Vector {
  constructor(... components) {this.components = components
  }
  // ...
  
  equalTo({ components }) {
    return components.every((component, index) = > areEqual(component, this.components[index]))
  }
}

const one = new Vector(1.2)
const other = new Vector(1.2)
console.log(one.equalTo(other))
// true
const another = new Vector(2.1)
console.log(one.equalTo(another))
// false
Copy the code

Unit vector and basis

We can view a vector as going along the X-axisOn the y axisOn the z-axisThe distance between. We can useMultiply each by a value to make the above more clear. The figures below are,,On the shaftA unit vector:


Any number timesI can get a vector that has a first dimension equal to that number. Such as:


The most important concept of vectors isThe basal. Let’s say I have a 3 dimensional vector, its basis is a set of vectors:This set of vectors can also beThe coordinate system of. ifIs a basis, and you can take any vectorRepresents the coefficient of the base:


vectorThrough theUpward direction measurementThe distance, inUpward direction measurementThe distance, inUpward direction measurementFrom the distance of.

The triplet of coefficients of a vector doesn’t mean much until you know its basis. If you know the basis of a vector, you can take something like thetaThe mathematical objects of triples are translated into real-world concepts (such as colors, probabilities, positions, and so on).

If you find any mistakes in your translation or other areas that need to be improved, you are welcome to the Nuggets Translation Program to revise and PR your translation, and you can also get the corresponding reward points. The permanent link to this article at the beginning of this article is the MarkDown link to this article on GitHub.


The Nuggets Translation Project is a community that translates quality Internet technical articles from English sharing articles on nuggets. The content covers Android, iOS, front-end, back-end, blockchain, products, design, artificial intelligence and other fields. If you want to see more high-quality translation, please continue to pay attention to the Translation plan of Digging Gold, the official Weibo, Zhihu column.