Skip to content

JavaScript 对象

作用域

变量是编程中的基本组成部分。我们声明变量来存储不同的数据类型。要声明变量,我们使用关键字 varletconst。变量可以在不同的作用域中声明。在本节中,我们将了解变量的作用域,以及使用 var 或 let 时变量的作用域。

变量作用域可以是:

  • 全局作用域
  • 局部作用域

变量可以在全局或局部作用域中声明。我们将看到全局和局部作用域。 任何不使用 let、var 或 const 声明的变量都在全局级别作用域。

窗口全局对象

不使用 console.log() 打开浏览器并检查,如果你在浏览器中写 a 或 b,你会看到 a 和 b 的值。这意味着 a 和 b 已经在窗口中可用。

js
//scope.js
a = 'JavaScript' // 不使用 let 或 const 声明变量会使其在窗口对象中可用,并且可以在任何地方找到
b = 10 // 这是一个全局作用域变量,在窗口对象中找到
function letsLearnScope() {
  console.log(a, b)
  if (true) {
    console.log(a, b)
  }
}
console.log(a, b) // 可访问

全局作用域

全局声明的变量可以在同一文件的任何地方访问。但是全局这个术语是相对的。它可以是文件的全局,也可以是相对于某些代码块的全局。

js
//scope.js
let a = 'JavaScript' // 是全局作用域,在此文件的任何地方都能找到
let b = 10 // 是全局作用域,在此文件的任何地方都能找到
function letsLearnScope() {
  console.log(a, b) // JavaScript 10,可访问
  if (true) {
    let a = 'Python'
    let b = 100
    console.log(a, b) // Python 100
  }
  console.log(a, b)
}
letsLearnScope()
console.log(a, b) // JavaScript 10,可访问

局部作用域

声明为局部的变量只能在某个代码块中访问。

  • 块作用域
  • 函数作用域
js
//scope.js
let a = 'JavaScript' // 是全局作用域,在此文件的任何地方都能找到
let b = 10 // 是全局作用域,在此文件的任何地方都能找到
// 函数作用域
function letsLearnScope() {
  console.log(a, b) // JavaScript 10,可访问
  let value = false
// 块作用域
  if (true) {
    // 我们可以从函数内部和函数外部访问
    // 但在 if 内部声明的变量不能在 if 块外部访问
    let a = 'Python'
    let b = 20
    let c = 30
    let d = 40
    value = !value
    console.log(a, b, c, value) // Python 20 30 true
  }
  // 我们不能访问 c,因为 c 的作用域只在 if 块内
  console.log(a, b, value) // JavaScript 10 true
}
letsLearnScope()
console.log(a, b) // JavaScript 10,可访问

现在,你对作用域有了理解。用 var 声明的变量只作用于函数,但用 letconst 声明的变量是块作用域(函数块、if 块、循环块等)。JavaScript 中的块是两个大括号 ({}) 之间的代码。

js
//scope.js
function letsLearnScope() {
  var gravity = 9.81
  console.log(gravity)
}
// console.log(gravity), Uncaught ReferenceError: gravity is not defined

if (true){
  var gravity = 9.81
  console.log(gravity) // 9.81
}
console.log(gravity)  // 9.81

for(var i = 0; i < 3; i++){
  console.log(i) // 0, 1, 2
}
console.log(i) // 3

在 ES6 及以上版本中有 letconst,所以你不会受到 var 的狡猾之苦。当我们使用 let 时,我们的变量是块作用域的,它不会影响代码的其他部分。

js
//scope.js
function letsLearnScope() {
  // 你可以使用 let 或 const,但 gravity 是常量,我更喜欢使用 const
  const gravity = 9.81
  console.log(gravity)
}
// console.log(gravity), Uncaught ReferenceError: gravity is not defined

if (true){
  const gravity = 9.81
  console.log(gravity) // 9.81
}
// console.log(gravity), Uncaught ReferenceError: gravity is not defined

for(let i = 0; i < 3; i++){
  console.log(i) // 0, 1, 2
}
// console.log(i), Uncaught ReferenceError: i is not defined

letconst 的作用域是相同的。区别只在于重新赋值。我们不能更改或重新赋值 const 变量的值。我强烈建议你使用 letconst,通过使用 letconst,你将编写干净的代码并避免难以调试的错误。作为经验法则,你可以对任何会改变的值使用 let,对任何常量值使用 const,对于数组、对象、箭头函数和函数表达式也是如此。

对象

一切都可以是对象,对象有属性,属性有值,所以对象是键值对。键的顺序不是保留的,或者没有顺序。 要创建对象字面量,我们使用两个大括号。

创建空对象

空对象:

js
const person = {}

创建带值的对象

现在,person 对象有 firstName、lastName、age、location、skills 和 isMarried 属性。属性或键的值可以是字符串、数字、布尔值、对象、null、undefined 或函数。

让我们看一些对象的例子。对象中的每个键都有一个值。

js
const rectangle = {
  length: 20,
  width: 20
}
console.log(rectangle) // {length: 20, width: 20}

const person = {
  firstName: 'Asabeneh',
  lastName: 'Yetayeh',
  age: 250,
  country: 'Finland',
  city: 'Helsinki',
  skills: [
    'HTML',
    'CSS',
    'JavaScript',
    'React',
    'Node',
    'MongoDB',
    'Python',
    'D3.js'
  ],
  isMarried: true
}
console.log(person)

从对象获取值

我们可以使用两种方法访问对象的值:

  • 使用 . 后跟键名(如果键名是一个单词)
  • 使用方括号和引号
js
const person = {
  firstName: 'Asabeneh',
  lastName: 'Yetayeh',
  age: 250,
  country: 'Finland',
  city: 'Helsinki',
  skills: [
    'HTML',
    'CSS',
    'JavaScript',
    'React',
    'Node',
    'MongoDB',
    'Python',
    'D3.js'
  ],
  getFullName: function() {
    return `${this.firstName}${this.lastName}`
  },
  'phone number': '+3584545454545'
}

// 使用 . 访问值
console.log(person.firstName)
console.log(person.lastName)
console.log(person.age)
console.log(person.location) // undefined

// 可以使用方括号和键名访问值
console.log(person['firstName'])
console.log(person['lastName'])
console.log(person['age'])
console.log(person['age'])
console.log(person['location']) // undefined

// 例如,要访问电话号码,我们只使用方括号方法
console.log(person['phone number'])

创建对象方法

现在,person 对象有 getFullName 属性。getFullName 是 person 对象内部的函数,我们称之为对象方法。this 关键字指的是对象本身。我们可以使用 this 来访问对象的不同属性的值。我们不能使用箭头函数作为对象方法,因为在箭头函数内部,this 指的是窗口而不是对象本身。对象示例:

js
const person = {
  firstName: 'Asabeneh',
  lastName: 'Yetayeh',
  age: 250,
  country: 'Finland',
  city: 'Helsinki',
  skills: [
    'HTML',
    'CSS',
    'JavaScript',
    'React',
    'Node',
    'MongoDB',
    'Python',
    'D3.js'
  ],
  getFullName: function() {
    return `${this.firstName} ${this.lastName}`
  }
}

console.log(person.getFullName())
// Asabeneh Yetayeh

为对象设置新键

对象是可变的数据结构,我们可以在对象创建后修改对象的内容。

在对象中设置新键:

js
const person = {
  firstName: 'Asabeneh',
  lastName: 'Yetayeh',
  age: 250,
  country: 'Finland',
  city: 'Helsinki',
  skills: [
    'HTML',
    'CSS',
    'JavaScript',
    'React',
    'Node',
    'MongoDB',
    'Python',
    'D3.js'
  ],
  getFullName: function() {
    return `${this.firstName} ${this.lastName}`
  }
}
person.nationality = 'Ethiopian'
person.country = 'Finland'
person.title = 'teacher'
person.skills.push('Meteor')
person.skills.push('SasS')
person.isMarried = true

person.getPersonInfo = function() {
  let skillsWithoutLastSkill = this.skills
    .splice(0, this.skills.length - 1)
    .join(', ')
  let lastSkill = this.skills.splice(this.skills.length - 1)[0]

  let skills = `${skillsWithoutLastSkill}, and ${lastSkill}`
  let fullName = this.getFullName()
  let statement = `${fullName} is a ${this.title}.\nHe lives in ${this.country}.\nHe teaches ${skills}.`
  return statement
}
console.log(person)
console.log(person.getPersonInfo())
sh
Asabeneh Yetayeh is a teacher.
He lives in Finland.
He teaches HTML, CSS, JavaScript, React, Node, MongoDB, Python, D3.js, Meteor, and SasS.

对象方法

有不同的方法来操作对象。让我们看看一些可用的方法。

Object.assign:复制对象而不修改原始对象

js
const person = {
  firstName: 'Asabeneh',
  age: 250,
  country: 'Finland',
  city:'Helsinki',
  skills: ['HTML', 'CSS', 'JS'],
  title: 'teacher',
  address: {
    street: 'Heitamienkatu 16',
    pobox: 2002,
    city: 'Helsinki'
  },
  getPersonInfo: function() {
    return `I am ${this.firstName} and I live in ${this.city}, ${this.country}. I am ${this.age}.`
  }
}

//对象方法:Object.assign, Object.keys, Object.values, Object.entries
//hasOwnProperty

const copyPerson = Object.assign({}, person)
console.log(copyPerson)

使用 Object.keys() 获取对象键

Object.keys:将对象的键或属性作为数组获取

js
const keys = Object.keys(copyPerson)
console.log(keys) //['firstName', 'age', 'country','city', 'skills','title', 'address', 'getPersonInfo']
const address = Object.keys(copyPerson.address)
console.log(address) //['street', 'pobox', 'city']

使用 Object.values() 获取对象值

Object.values:将对象的值作为数组获取

js
const values = Object.values(copyPerson)
console.log(values)

使用 Object.entries() 获取对象键和值

Object.entries:在数组中获取键和值

js
const entries = Object.entries(copyPerson)
console.log(entries)

使用 hasOwnProperty() 检查属性

hasOwnProperty:检查对象中是否存在特定的键或属性

js
console.log(copyPerson.hasOwnProperty('name'))
console.log(copyPerson.hasOwnProperty('score'))

🌕 你太棒了。现在,你拥有了对象的强大力量。你刚刚完成了第8天的挑战,你在通往伟大的道路上前进了8步。现在为你的大脑和肌肉做一些练习。

💻 练习

练习:级别 1

  1. 创建一个名为 dog 的空对象
  2. 在控制台上打印 dog 对象
  3. 为 dog 对象添加 name、legs、color、age 和 bark 属性。bark 属性是一个返回 woof woof 的方法
  4. 从 dog 对象获取 name、legs、color、age 和 bark 值
  5. 为 dog 对象设置新属性:breed、getDogInfo

练习:级别 2

  1. 在 users 对象中找到拥有最多技能的人。

  2. 从以下对象中计算已登录用户,计算积分大于等于50的用户。

    js
    const users = {
      Alex: {
        email: 'alex@alex.com',
        skills: ['HTML', 'CSS', 'JavaScript'],
        age: 20,
        isLoggedIn: false,
        points: 30
      },
      Asab: {
        email: 'asab@asab.com',
        skills: ['HTML', 'CSS', 'JavaScript', 'Redux', 'MongoDB', 'Express', 'React', 'Node'],
        age: 25,
        isLoggedIn: false,
        points: 50
      },
      Brook: {
        email: 'daniel@daniel.com',
        skills: ['HTML', 'CSS', 'JavaScript', 'React', 'Redux'],
        age: 30,
        isLoggedIn: true,
        points: 50
      },
      Daniel: {
        email: 'daniel@alex.com',
        skills: ['HTML', 'CSS', 'JavaScript', 'Python'],
        age: 20,
        isLoggedIn: false,
        points: 40
      },
      John: {
        email: 'john@john.com',
        skills: ['HTML', 'CSS', 'JavaScript', 'React', 'Redux', 'Node.js'],
        age: 20,
        isLoggedIn: true,
        points: 50
      },
      Thomas: {
        email: 'thomas@thomas.com',
        skills: ['HTML', 'CSS', 'JavaScript', 'React'],
        age: 20,
        isLoggedIn: false,
        points: 40
      },
      Paul: {
        email: 'paul@paul.com',
        skills: ['HTML', 'CSS', 'JavaScript', 'MongoDB', 'Express', 'React', 'Node'],
        age: 20,
        isLoggedIn: false,
        points: 40
      }
    }
  3. 从 users 对象中找到 MERN 栈开发者

  4. 在不修改原始 users 对象的情况下,在 users 对象中设置你的名字

  5. 获取 users 对象的所有键或属性

  6. 获取 users 对象的所有值

  7. 使用 countries 对象打印国家名称、首都、人口和语言。

练习:级别 3

  1. 创建一个名为 personAccount 的对象字面量。它有 firstName, lastName, incomes, expenses 属性,并且有 totalIncome, totalExpense, accountInfo, addIncome, addExpenseaccountBalance 方法。Incomes 是一组收入及其描述,expenses 是一组支出及其描述。

  2. **** 问题:2、3 和 4 基于以下两个数组:users 和 products

js
    const users = [
    {
        _id: 'ab12ex',
        username: 'Alex',
        email: 'alex@alex.com',
        password: '123123',
        createdAt:'08/01/2020 9:00 AM',
        isLoggedIn: false
    },
    {
        _id: 'fg12cy',
        username: 'Asab',
        email: 'asab@asab.com',
        password: '123456',
        createdAt:'08/01/2020 9:30 AM',
        isLoggedIn: true
    },
    {
        _id: 'zwf8md',
        username: 'Brook',
        email: 'brook@brook.com',
        password: '123111',
        createdAt:'08/01/2020 9:45 AM',
        isLoggedIn: true
    },
    {
        _id: 'eefamr',
        username: 'Martha',
        email: 'martha@martha.com',
        password: '123222',
        createdAt:'08/01/2020 9:50 AM',
        isLoggedIn: false
    },
    {
        _id: 'ghderc',
        username: 'Thomas',
        email: 'thomas@thomas.com',
        password: '123333',
        createdAt:'08/01/2020 10:00 AM',
        isLoggedIn: false
    }
    ];

    const products = [
  {
    _id: 'eedfcf',
    name: 'mobile phone',
    description: 'Huawei Honor',
    price: 200,
    ratings: [
      { userId: 'fg12cy', rate: 5 },
      { userId: 'zwf8md', rate: 4.5 }
    ],
    likes: []
  },
  {
    _id: 'aegfal',
    name: 'Laptop',
    description: 'MacPro: System Darwin',
    price: 2500,
    ratings: [],
    likes: ['fg12cy']
  },
  {
    _id: 'hedfcg',
    name: 'TV',
    description: 'Smart TV:Procaster',
    price: 400,
    ratings: [{ userId: 'fg12cy', rate: 5 }],
    likes: ['fg12cy']
  }
]

想象你从 MongoDB 数据库获取上述用户集合。 a. 创建一个名为 signUp 的函数,允许用户添加到集合中。如果用户存在,告知用户他已经有一个账户。
b. 创建一个名为 signIn 的函数,允许用户登录应用程序

  1. products 数组有三个元素,每个元素都有六个属性。 a. 创建一个名为 rateProduct 的函数来评价产品 b. 创建一个名为 averageRating 的函数来计算产品的平均评分

  2. 创建一个名为 likeProduct 的函数。这个函数将帮助喜欢产品(如果它没有被喜欢)并移除喜欢(如果它被喜欢了)。

🎉 恭喜!🎉