前端面试之变量与数据类型

目录

一、声明变量

(1)let

(2)const

(3)var

var、let 和 const 的作用域差异

二、数据类型 

(1)基本类型

undefined和null

String 

模板字符串拼接:

number和bigint 

字符串转换为整数 :

 boolean

symbol

二、对象类型 

(1)Function函数

1.函数声明

2.函数表达式 

3.箭头函数

4.匿名函数

函数作用域

闭包 

(2)Array数组

常用数组方法

1.添加/删除元素

 2.合并/拼接数组

 3.查找元素

 4.遍历数组

 5.排序和反转

 6.其他实用方法

7. ES6+ 新增数组特性

1.扩展运算符

2. 解构赋值

 3.Array.from()

(3)Object对象

创建对象

访问属性

添加/修改属性

删除属性

常用静态方法

 对象实例方法

原型与继承

原型基础

更规范的继承方式

构造函数与原型

ES6+ 对象新特性

属性简写

计算属性名

对象解构

扩展运算符

对象与JSON


一、声明变量

(1)let
  • let声明的变量可以多次赋值。

(2)const
  • const修饰的值叫常量,只能赋值一次。

(3)var
  • var声明的变量可以多次赋值。
var、let 和 const 的作用域差异
  1. var:函数作用域

    • 在函数内部声明的变量只能在函数内部访问
    • 没有块级作用域
  2. let/const:块级作用域

    • 在 {} 块中声明的变量只能在该块中访问
    • 解决了 var 的变量提升和重复声明问题
function varExample() {
  if (true) {
    var x = 10;
    let y = 20;
  }
  console.log(x); // 10 (var 没有块级作用域)
  console.log(y); // 报错:y is not defined (let 有块级作用域)
}

varExample();

二、数据类型 

(1)基本类型
undefined和null

undefined表示变量已被声明,但尚未被赋值。也就是说,变量存在,但没有具体的值。

  • 变量声明后未赋值时,默认值为 undefined

  • 如果函数没有返回值,那么它的返回值默认也是 undefined

  • 如果访问对象中不存在的属性,其值也是 undefined

    let a; // 声明变量 a,未赋值
    console.log(a); // 输出:undefined
    
    function test() {
      // 没有返回值
    }
    console.log(test()); // 输出:undefined
    
    const obj = {};
    console.log(obj.property); // 输出:undefined

    null表示“空值”或“无对象”。

  • 明确表示变量的值为空,而不是未赋值。

  • 在类型检查中,null 是一个独立的类型,即 null 的类型是 object

总结:

  • undefined 表示变量未被赋值,是一个“未定义”的状态。

  • null 表示变量被明确赋值为空,是一个“空值”或“无对象”的状态。

String 

字符串是由字符组成的序列,用于表示文本数据。在 JavaScript 中,字符串可以用单引号(')、双引号(")或反引号(`)来定义。 

let singleQuoted = 'Hello, world!';
let doubleQuoted = "Hello, world!";
let backtickQuoted = `Hello, world!`;

console.log(singleQuoted); // 输出:Hello, world!
console.log(doubleQuoted); // 输出:Hello, world!
console.log(backtickQuoted); // 输出:Hello, world!

传统字符串拼接:

let name = "Alice";
let age = 30;
let greeting = "Hello, " + name + "! You are " + age + " years old.";
console.log(greeting); // 输出:Hello, Alice! You are 30 years old.
模板字符串拼接:

(模板字符串是 ES6 的新特性)

模板字符串(Template Literals)是 ES6 引入的一种新的字符串表示方式,使用反引号(`)定义,并支持嵌入表达式和多行字符串。

let name = "Alice";
let age = 30;
let greeting = `Hello, ${name}! You are ${age} years old.`;
console.log(greeting); // 输出:Hello, Alice! You are 30 years old.
number和bigint 

Number 类型基于 IEEE 754 标准的双精度浮点数表示,因此可以表示小数。可以表示的数值范围是 -2^53 + 12^53 - 1。由于 Number 是基于浮点数表示的,因此在处理大整数或高精度计算时可能会出现精度问题。

console.log(0.1 + 0.2); // 输出:0.30000000000000004
console.log(9007199254740991 + 1); // 输出:9007199254740992
console.log(9007199254740992 + 1); // 输出:9007199254740992(精度丢失)
字符串转换为整数 :

1.parseInt

console.log(parseInt("12345")); // 输出:12345
console.log(parseInt("123.45")); // 输出:123(忽略小数部分)
console.log(parseInt("123abc")); // 输出:123(忽略非数字部分)
console.log(parseInt("abc123")); // 输出:NaN(开头不是数字)

 2.Number 构造函数

console.log(Number("123.45")); // 输出:123.45
console.log(Number("123abc")); // 输出:NaN

 3.一元加号运算符

console.log(+ "123.45"); // 输出:123.45
console.log(+ "123abc"); // 输出:NaN

 BigInt 是 ES2020 引入的一种新的数值类型,用于表示任意大小的整数。BigInt 可以表示任意大小的整数,没有上限。BigInt 保证整数的精确表示,不会出现精度问题。BigInt 字面量以 n 结尾,例如 123n。BigInt 支持基本的算术运算,但不能与 Number 类型直接进行运算,需要显式转换。

// Number
let num1 = 12345678901234567890;
let num2 = 12345678901234567890;
console.log(num1 + num2); // 输出:24691357802469135780,但可能会有精度问题

// BigInt
let bigInt1 = 12345678901234567890n;
let bigInt2 = 12345678901234567890n;
console.log(bigInt1 + bigInt2); // 输出:24691357802469135780n,精确无误
 boolean

在 JavaScript 中,truthyfalsy 是两个非常重要的概念,用于描述值在布尔上下文中的表现。这些概念在条件语句(如 ifwhile 等)和逻辑运算中非常重要。

falsy:false、0、-0、""(空字符串)、null、undefined、NaN

truthy:true、1、{}(空对象)、[](空数组)等。

symbol

在 JavaScript 中,Symbol 是一种原始数据类型,用于表示唯一的、不可变的值。Symbol 是 ES6(ECMAScript 2015)引入的,旨在解决对象属性名称冲突的问题,并提供一种更安全的方式来定义对象的属性。

二、对象类型 

(1)Function函数

函数本质上是对象。这使得函数具有对象的特性,例如可以拥有属性和方法,可以作为变量赋值,可以作为参数传递,也可以作为返回值。这种特性使得 JavaScript 的函数非常强大和灵活。

1.函数声明
function greet(name) {
  return `Hello, ${name}!`;
}

console.log(greet("Alice")); // 输出:Hello, Alice!
2.函数表达式 
const greet = function(name) {
  return `Hello, ${name}!`;
};

console.log(greet("Bob")); // 输出:Hello, Bob!
3.箭头函数

ES6 引入了箭头函数(Arrow Function),它是一种更简洁的匿名函数语法。箭头函数省略了 function 关键字,并且可以省略花括号和 return 关键字(如果函数体只有一条语句)。

const greet = (name) => `Hello, ${name}!`;

console.log(greet("Charlie")); // 输出:Hello, Charlie!
4.匿名函数

匿名函数也经常被用作高阶函数的参数,例如 mapfilterreduce

const numbers = [1, 2, 3, 4, 5];
const squared = numbers.map(function(num) {
  return num * num;
});

console.log(squared); // 输出:[1, 4, 9, 16, 25]
函数作用域
  1. 函数作用域:在函数内部声明的变量只能在函数内部访问
  2. 局部变量:函数内部声明的变量
  3. 全局变量:函数外部声明的变量

JavaScript 使用作用域链来解析变量:

  1. 首先在当前函数作用域查找
  2. 如果找不到,向上一级作用域查找
  3. 直到全局作用域
  4. 如果全局作用域也没有,则报错
var a = 1;

function outer() {
  var b = 2;
  
  function inner() {
    var c = 3;
    console.log(a + b + c); // 6 (可以访问所有外层变量)
  }
  
  inner();
}

outer();
闭包 

闭包是指一个函数能够记住并访问其词法作用域,即使该函数在其词法作用域之外执行。

简单来说,闭包让函数可以"记住"它被创建时的环境,即使这个函数在创建它的环境之外被调用。

function outer() {
  let count = 0; // 外部函数的局部变量
  
  function inner() {
    count++; // 内部函数访问外部函数的变量
    console.log(count);
  }
  
  return inner; // 返回内部函数
}

const counter = outer();
counter(); // 1
counter(); // 2
counter(); // 3

 在这个例子中,inner 函数就是一个闭包,它可以访问 outer 函数的 count 变量,即使 outer 函数已经执行完毕

闭包的特点

1.记忆环境:闭包会记住创建时的词法环境

2.持久性:闭包中的变量会一直存在,不会被垃圾回收

3.私有性:可以创建私有变量和方法

(2)Array数组

常用数组方法
1.添加/删除元素
方法描述返回值是否修改原数组
push()末尾添加一个或多个元素新长度
pop()删除最后一个元素被删除元素
unshift()开头添加一个或多个元素新长度
shift()删除第一个元素被删除元素
let arr = [1, 2, 3];

arr.push(4); // [1, 2, 3, 4]
arr.pop();   // [1, 2, 3]
arr.unshift(0); // [0, 1, 2, 3]
arr.shift();    // [1, 2, 3]
 2.合并/拼接数组
// concat() - 合并数组(不修改原数组)
let arr1 = [1, 2];
let arr2 = [3, 4];
let combined = arr1.concat(arr2); // [1, 2, 3, 4]

// splice() - 强大的数组修改方法(修改原数组)
let fruits = ['Apple', 'Banana', 'Orange'];
fruits.splice(1, 1, 'Mango', 'Peach'); 
// 从索引1开始,删除1个元素,插入'Mango'和'Peach'
// 结果: ['Apple', 'Mango', 'Peach', 'Orange']
 3.查找元素
let numbers = [1, 2, 3, 4, 5, 4, 3, 2, 1];

// indexOf() - 查找元素首次出现的位置
console.log(numbers.indexOf(3)); // 2

// lastIndexOf() - 查找元素最后一次出现的位置
console.log(numbers.lastIndexOf(3)); // 6

// includes() - 检查是否包含某元素
console.log(numbers.includes(5)); // true

// find() - 查找第一个符合条件的元素
let found = numbers.find(item => item > 3); // 4

// findIndex() - 查找第一个符合条件的元素索引
let foundIndex = numbers.findIndex(item => item > 3); // 3
 4.遍历数组
let fruits = ['Apple', 'Banana', 'Orange'];

// forEach() - 遍历数组
fruits.forEach(function(item, index) {
  console.log(index, item);
});

// map() - 映射新数组
let lengths = fruits.map(fruit => fruit.length); // [5, 6, 6]

// filter() - 过滤数组
let longFruits = fruits.filter(fruit => fruit.length > 5); // ['Banana', 'Orange']

// reduce() - 累积计算
let numbers = [1, 2, 3, 4];
let sum = numbers.reduce((total, num) => total + num, 0); // 10
 5.排序和反转
let numbers = [3, 1, 4, 2, 5];

// sort() - 排序(修改原数组)
numbers.sort(); // [1, 2, 3, 4, 5]

// 自定义排序
let scores = [88, 95, 70, 92];
scores.sort((a, b) => b - a); // 降序排序 [95, 92, 88, 70]

// reverse() - 反转数组(修改原数组)
numbers.reverse(); // [5, 4, 3, 2, 1]
 6.其他实用方法
// slice() - 截取数组(不修改原数组)
let arr = [1, 2, 3, 4, 5];
let part = arr.slice(1, 3); // [2, 3]

// join() - 数组转字符串
let str = arr.join('-'); // "1-2-3-4-5"

// Array.isArray() - 检查是否为数组
console.log(Array.isArray(arr)); // true

// fill() - 填充数组
let newArr = new Array(3).fill(0); // [0, 0, 0]

// flat() - 扁平化数组
let nested = [1, [2, [3]]];
let flatArr = nested.flat(2); // [1, 2, 3]
7. ES6+ 新增数组特性
1.扩展运算符
// 复制数组
let arr = [1, 2, 3];
let arrCopy = [...arr]; // [1, 2, 3]

// 合并数组
let combined = [...arr, 4, 5, ...[6, 7]]; // [1, 2, 3, 4, 5, 6, 7]
2. 解构赋值
let [first, second, ...rest] = [1, 2, 3, 4, 5];
console.log(first); // 1
console.log(second); // 2
console.log(rest); // [3, 4, 5]
 3.Array.from()
// 从类数组对象创建数组
let arrayLike = {0: 'a', 1: 'b', length: 2};
let realArray = Array.from(arrayLike); // ['a', 'b']

// 从可迭代对象创建数组
let set = new Set([1, 2, 3]);
let arrayFromSet = Array.from(set); // [1, 2, 3]

(3)Object对象

对象是 JavaScript 中最重要的数据类型之一,用于存储键值对集合。几乎所有 JavaScript 的值都可以视为对象,除了原始类型(string、number、boolean、null、undefined、symbol、bigint)。

创建对象
// 1. 对象字面量语法(最常用)
let person = {
  name: '张三',
  age: 30,
  isStudent: false
};

// 2. 使用 Object 构造函数
let car = new Object();
car.make = 'Toyota';
car.model = 'Camry';

// 3. 使用 Object.create()
let animal = Object.create(null);
animal.type = 'dog';
访问属性
// 点表示法
console.log(person.name); // '张三'

// 方括号表示法(适用于动态属性名或包含特殊字符的属性名)
console.log(person['age']); // 30

let key = 'isStudent';
console.log(person[key]); // false
添加/修改属性
// 添加新属性
person.job = '工程师';

// 修改现有属性
person.age = 31;

// 使用方括号表示法
person['favorite color'] = '蓝色'; // 属性名包含空格时
删除属性
delete person.isStudent; // 删除属性
console.log(person.isStudent); // undefined
常用静态方法
// Object.keys() - 获取对象所有可枚举属性的键
let keys = Object.keys(person); // ['name', 'age', 'job', 'favorite color']

// Object.values() - 获取对象所有可枚举属性的值
let values = Object.values(person); // ['张三', 31, '工程师', '蓝色']

// Object.entries() - 获取键值对数组
let entries = Object.entries(person); 
// [ ['name', '张三'], ['age', 31], ['job', '工程师'], ['favorite color', '蓝色'] ]

// Object.assign() - 合并对象(浅拷贝)
let target = { a: 1 };
let source = { b: 2, c: 3 };
Object.assign(target, source); // { a: 1, b: 2, c: 3 }

// Object.freeze() - 冻结对象,防止修改
let frozenObj = Object.freeze({ x: 1 });
frozenObj.x = 2; // 静默失败(严格模式下会报错)
 对象实例方法
let obj = {
  name: '示例对象',
  // 定义方法
  greet: function() {
    return `你好,我是${this.name}`;
  },
  // ES6简写方法语法
  sayHello() {
    return 'Hello!';
  }
};

console.log(obj.greet()); // "你好,我是示例对象"
console.log(obj.sayHello()); // "Hello!"
原型与继承
原型基础
// 每个对象都有一个原型(__proto__属性,不推荐直接使用)
let animal = {
  eats: true
};

let rabbit = {
  jumps: true,
  __proto__: animal // 设置原型(现代写法应使用Object.create)
};

console.log(rabbit.eats); // true (通过原型继承)
更规范的继承方式
// 使用Object.create()创建带有指定原型的对象
let animal = {
  eats: true
};

let rabbit = Object.create(animal);
rabbit.jumps = true;

console.log(rabbit.eats); // true
构造函数与原型
// 构造函数
function Person(name, age) {
  this.name = name;
  this.age = age;
}

// 通过原型添加方法
Person.prototype.greet = function() {
  return `你好,我是${this.name},今年${this.age}岁`;
};

let john = new Person('John', 30);
console.log(john.greet()); // "你好,我是John,今年30岁"
ES6+ 对象新特性
属性简写
let name = '李四';
let age = 25;

let person = {
  name,  // 等同于 name: name
  age,   // 等同于 age: age
  greet() {
    return `我是${this.name}`;
  }
};
计算属性名
let propKey = 'foo';

let obj = {
  [propKey]: true,
  ['b' + 'ar']: 123,
  [Symbol('id')]: 'symbolId'
};

console.log(obj.foo); // true
console.log(obj.bar); // 123
对象解构
let options = {
  title: '菜单',
  width: 100,
  height: 200
};

// 解构赋值
let { title, width, height } = options;

console.log(title);  // '菜单'
console.log(width);  // 100
console.log(height); // 200
扩展运算符
let obj1 = { a: 1, b: 2 };
let obj2 = { c: 3, d: 4 };

let merged = { ...obj1, ...obj2 }; // { a: 1, b: 2, c: 3, d: 4 }
对象与JSON
// 对象转JSON字符串
let user = {
  name: "张三",
  age: 30
};

let json = JSON.stringify(user);
console.log(json); // '{"name":"张三","age":30}'

// JSON字符串转对象
let parsed = JSON.parse(json);
console.log(parsed.name); // "张三"

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值