JavaScript基础

JavaScript基本数据类型

8种数据类型

最新的 ECMAScript 标准定义了 8 种数据类型

Boolean、Null、Undefined、Number、String、Symbol、BigInt和Object,前面七个称为原始类型,其中Symbol和BigInt是ES6以后新出的数据类型

Boolean 表示一个逻辑实体,可以有两个值:true 和 false。
Null 只有一个值: null,更多详情可查看 null 和 Null 。
Undefined 类型:一个没有被赋值的变量会有个默认值 undefined。
Number 根据 ECMAScript 标准,JavaScript 中只有一种数字类型:基于 IEEE 754 标准的双精度 64 位二进制格式的值 (-(253 -1) 到 253 -1) 。它并没有为整数给出一种特定的类型。除了能够表示浮点数外,还有一些带符号的值:+Infinity(正无穷),-Infinity(负无穷) 和 NaN (非数值,Not-a-Number)。
String 用于表示文本数据。String 有最大长度是 253 - 1。此处的长度不是字符数,是字符串的 UTF16 编码。
Object 在 Javascript 里,对象可以被看作是一组属性的集合。用对象字面量语法来定义一个对象时,会自动初始化一组属性(也就是说,定义一个var a = "Hello",那么a本身就会有a.substring这个方法,以及a.length这个属性,以及其它;如果你定义了一个对象,var a = {},那么a就会自动有a.hasOwnPropertya.constructor等属性和方法)。这些属性还可以被增减。属性的值可以是任意类型,包括具有复杂数据结构的对象。

注意:

根据双精度浮点数的定义,Number 类型中有效的整数范围是 -0x1fffffffffffff 至 0x1fffffffffffff,所以 Number 无法精确表示此范围外的整数。

同样根据浮点数的定义,非整数的 Number 类型无法用 = 也不行) 来比较,0.1 + 0.2 == 0.3是false。这是浮点运算精度问题的特点,差了一个微小的值。正确的比较方法是使用 JavaScript 提供的最小精度值Math.abs(0.1 + 0.2 - 0.3) <= Number.EPSILON是true。

typeOf数据类型判断

typeof undefined	// "undefined"
typeof 'abc'		// "string"
typeof 123			// "number"
typeof true			// "boolean"
typeof {}			// "object"
typeof []			// "object"
typeof null			// "object"
typeof console.log	// "function"
typeof Symbol		// "function"

typeof 的运算结果,与运行时类型的规定有很多不一致的地方

示例表达式typeof结果运行时类型行为
nullobjectNull
{}objectObject
(function(){})functionObject
3numberNumber
“ok”stringString
truebooleanBoolean
void 0undefinedUndefined
Symbol(“a”)symbolSymbol

判断数组类型

  1. instanceof

    function isArray (obj) {
    	return obj instanceof Array;
    }
    
  2. 对象的constructor属性

    var arr = [1,2,3,1]; 
    alert(arr.constructor === Array); // true 
    
  3. Object.prototype.toString

    function isArray (obj) {
    	return Object.prototype.toString.call(obj) === '[object Array]';
    }
    
  4. Array对象的 isArray方法( Array.isArray() )

    function isArray (obj) {
    	return Array.isArray(obj);
    }
    

操作数组的基本方法

JavaScript的 Array 对象是用于构造数组的全局对象,数组是类似于列表的高阶对象。

创建数组

let fruits = ['Apple', 'Banana'];
console.log(fruits.length);

通过索引访问数组元素

let first = fruits[0];						// Apple
let last = fruits[fruits.length - 1];		// Banana

遍历数组

fruits.forEach(function (item, index, array) {
    console.log(item, index);
});
// Apple 0
// Banana 1

// 或者写成箭头函数(array此处没用 可删除)
let tempArr = []
fruits.forEach((item, index, array) => {
    // 模板字符串
    tempArr.push(`${item}-${index}`)
});
console.log(tempArr);

找出某个元素在数组中的索引

fruits.push('Mango');
// ["Strawberry", "Banana", "Mango"]
let pos = fruits.indexOf('Banana');
// 1

通过索引删除某个元素

let removedItem = fruits.splice(pos, 1); 
// ["Strawberry", "Mango"]

复制一个数组

let shallowCopy = fruits.slice();

其他常规操作

push() pop() shift() unshift()

push() 将一个或多个元素添加到数组的末尾,并返回该数组的新长度。

pop() 从数组中删除最后一个元素,并返回该元素的值。此方法更改数组的长度。

shift() 从数组中删除第一个元素,并返回该元素的值。此方法更改数组的长度。

unshift() 将一个或多个元素添加到数组的开头,并返回该数组的新长度(该方法修改原有数组**)**。

concat()

用于合并两个或多个数组。此方法不会更改现有数组,而是返回一个新数组。

应用场景1:连接两个数组

let a = ['a', 'b', 'c'];
let b = [1, 2, 3];
a.concat(b);
// result in ['a', 'b', 'c', 1, 2, 3]

应用场景2:复制数组(浅拷贝)

let a = ['a', 'b', 'c'];
let copyA = [].concat(a);
console.log(copyA);

every()

测试一个数组内的所有元素是否都能通过某个指定函数的测试。它返回一个布尔值。

[100, 5, 8, 130, 44].every(x => x >= 10);	// false
[33, 54, 18, 130, 44].every(x => x >= 10);	// true

filter()

创建一个新数组,其包含通过所提供函数实现的测试的所有元素。经常在前端展示数据或者根据条件过滤用到。

const words = ['spray', 'limit', 'elite', 'exuberant', 'destruction', 'present'];
const result = words.filter(word => word.length > 6);
console.log(result);
// expected output: Array ["exuberant", "destruction", "present"]

some()

测试数组中是不是至少有1个元素通过了被提供的函数测试。它返回的是一个Boolean类型的值。

const array = [1, 2, 3, 4, 5];
// checks whether an element is even
const even = (element) => element % 2 === 0;
console.log(array.some(even));

forEach()

按升序为数组中含有效值的每一项执行一次 callback 函数,那些已删除或者未初始化的项将被跳过(例如在稀疏数组上)。

forEach() 被调用时,不会改变原数组,也就是调用它的数组(尽管 callback 函数在被调用时可能会改变原数组)。

此方法经常在循环遍历数组的时候用到,代替for循环,清晰明了。

function logArrayElements(element, index, array) {
  console.log('a[' + index + '] = ' + element);
}

// 注意索引 2 被跳过了,因为在数组的这个位置没有项
[2, 5, , 9].forEach(logArrayElements);

map()

创建一个新数组,其结果是该数组中的每个元素都调用一次提供的函数后的返回值。

此方法在对数组进行特性化处理的时候经常用到。

const array1 = [1, 4, 9, 16];

// pass a function to map
const map1 = array1.map(x => x * 2);

console.log(map1);
// expected output: Array [2, 8, 18, 32]

reduce()

对数组中的每个元素执行一个由您提供的reducer函数(升序执行),将其结果汇总为单个返回值。

arr.reduce(callback(accumulator, currentValue[, index[, array]])[, initialValue])

此方法在做高阶函数或者对数据进行迭代化处理的时候经常用到。

let initialValue = 0;
let sum = [{x: 1}, {x:2}, {x:3}].reduce(function (accumulator, currentValue) {
    return accumulator + currentValue.x;
},initialValue)

console.log(sum) // logs 6

includes()

用来判断一个数组是否包含一个指定的值,根据情况,如果包含则返回 true,否则返回false。

const array1 = [1, 2, 3];

console.log(array1.includes(2));
// expected output: true

includes() 可以给数组用 也可以给字符串用

let s = 'amd'
console.log(s.includes('m'))

sort()

原地算法对数组的元素进行排序,并返回数组。默认排序顺序是在将元素转换为字符串,然后比较它们的UTF-16代码单元值序列时构建的。

let numbers = [4, 2, 5, 1, 3];
numbers.sort(function(a, b) {	// 前减后(此处是a-b)是升序 反之降序
  return a - b;
});
console.log(numbers);

JS中操作对象的基本方法

Object 构造函数为给定值创建一个对象包装器。如果给定值是 nullundefined,将会创建并返回一个空对象,否则,将返回一个与给定值对应类型的对象。

对象在JS中的地位可谓是相当的高,像原型原型链这些东西都是从对象衍生出来的。

创建对象

字面量方式

let a = {}

使用构造函数

function Car(make, model, year) {
  this.make = make;
  this.model = model;
  this.year = year;
}
let mycar = new Car("Eagle", "Talon TSi", 1993);

使用Object.create方法

Object.create()方法创建的对象时,属性是在原型下面的。

const person = {
  isHuman: false,
  printIntroduction: function() {
    console.log(`My name is ${this.name}. Am I human? ${this.isHuman}`);
  }
};

const me = Object.create(person);

me.name = 'Matthew'; // "name" is a property set on "me", but not on "person"
me.isHuman = true; // inherited properties can be overwritten

me.printIntroduction();

核心API

assign()

Object.assign() 方法用于将所有可枚举属性的值从一个或多个源对象复制到目标对象。它将返回目标对象。

const target = { a: 1, b: 2 };
const source = { b: 4, c: 5 };
const returnedTarget = Object.assign(target, source);
// 如果目标对象中的属性具有相同的键,则属性将被源对象中的属性覆盖。后面的源对象的属性将类似地覆盖前面的源对象的属性。
console.log(target);
// expected output: Object { a: 1, b: 4, c: 5 }
console.log(returnedTarget);
// expected output: Object { a: 1, b: 4, c: 5 }

// ES6解构
console.log({...target,...source})

hasOwnProperty()

会返回一个布尔值,指示对象自身属性中是否具有指定的属性(即:是否有指定的键)。

const object1 = {
    property1:42
};
console.log(object1.hasOwnProperty('property1'));
// expected output: true
console.log(object1.hasOwnProperty('toString'));
// expected output: false
console.log(object1.hasOwnProperty('hasOwnProperty'));

for…in

以任意顺序遍历一个对象的除Symbol以外的可枚举属性。用此方法遍历对象非常方便。

let obj = {a:1, b:2, c:3};
    
for (let prop in obj) {
  console.log("obj." + prop + " = " + obj[prop]);
}

JS的模块化导入导出

CommonJsAMDCMDES6都是用于模块化定义中使用的规范,其为了规范化模块的引入与处理模块之间的依赖关系以及解决命名冲突问题,并使用模块化方案来使复杂系统分解为代码结构更合理,可维护性更高的可管理的模块。
在这里插入图片描述

CommonJS

概述

CommonJS 规范是为了解决 JavaScript 的作用域问题而定义的模块形式,可以使每个模块它自身的命名空间中执行。每个模块就是一个模块,有自己的作用域。在一个文件里面定义的变量,函数,类都是私有的,对其他文件不可见。在服务器端,模块的加载是运行时同步加载的;在浏览器端,模块需要提前编译打包处理。

CommonJS 一般是在 做构建工具、打包的配置、写一些node脚本 的时候会用到的规范

特点

  • 所有代码都运行在模块作用域,不会污染全局作用域。
  • 模块可以多次加载,但是只会在第一次加载的时运行一次,然后运行结果就被缓存了,以后再加载就直接读取缓存结果。要想让模块再次运行,必须清除缓存。
  • 模块加载的顺序,按照其在代码中出现的顺序。

语法

// 导出
function test (a,b) {
  console.log(a + b)
}
module.exports = test
// 或者直接写成
module.exports = function test (a,b) {
  console.log(a + b)
}

// 导入
let test = require('./test.js')

test(1,2)

Es6中的模块化

概述

ES6 在语言标准的层面上,实现了模块功能,而且实现得相当简单,旨在成为浏览器和服务器通用的模块解决方案。ES6 模块的设计思想是尽量的静态化,使得编译时就能确定模块的依赖关系,以及输入和输出的变量。

基本语法

export 导出模式
  • 导出
// export-test.js
let add = function (a, b) {
    return a + b;
};
export { add };
  • 引入
// import-test.js
import { add } from '/export-test.js';
function test() {
  let res = add(99,1)
  console.log(res)
}
test()

导入导出 例子

// 导出
function test (a,b) {
  console.log(a + b)
}
module.exports = test
// 或者直接写成
module.exports = function test (a,b) {
  console.log(a + b)
}

// 导入
let test = require('./test.js')

test(1,2)
export default导出模式
  • 导出
// export-default.js
export default function () {
  console.log('foo');
}

// 上面代码是一个模块文件export-default.js,它的默认输出是一个函数。
// 其他模块加载该模块时,import命令可以为该匿名函数指定任意名字。
  • 引入
// import-default.js
import customName from './export-default';
customName(); // 'foo'
// 上面代码的import命令,可以用任意名称指向export-default.js输出的方法,这时就不需要知道原模块输出的函数名。
// 需要注意的是,这时import命令后面,不使用大括号。

export和export default差异

  • export、import可以有多个,而export default只能有一个
  • export导出的对象在导入时需要加{},而export default则不需要
  • export能直接导出变量表达式
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值