《JavaScript高级程序设计》__ 语言基础(上)(2)

本文涉及的产品
全局流量管理 GTM,标准版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
云解析 DNS,旗舰版 1个月
简介: 前言大家好,我是HoMeTown,web领域有一本神书大家应该都有看过,这本书我看过两遍,但是每次看都是粗粗的略过一些重要的知识点,甚至一些面试过程中的问题,在这本书里都能找到答案。

浮点数

JavaScript会自动判断你的浮点数是否有意义,比如1.0,这样的数会自动保存成1,因为存储一个浮点数的开销比存储一个整数大得多。

可以用浮点数 + 科学计数法来表示一个大数:

const num = 3.123e7 // 31230000
复制代码

字母e后面的数字表示再加上一个要乘的 10 的多少次幂,反之一样,比如31230000e-7

0.1 + 0.2 != 0.3,而是0.300 000 000 000 000 04,双精度和单精度计算出来的结果还不一样,这是是因为使用了 IEEE 754 数值,这种错误并非 ECMAScript所独有。其他使用相同格式的语言也有这个问题。

部分浮点数在十进制下是有限小数,但是在二进制下尾数是无限数,比如0.1、0.2 尾数0011无限循环。

由于计算精度有限,计算机底层根据IEEE 754舍入规则进行处理后存储了一个近似值(近似值的长度与精度有关),近似值0.3值0.3 在二进制上表现不同,是不能用来比较的,因为近似值和任何数比较都可能返回false。

值的范围

Number.MIN_VALUE // 最小值 5e-324
Number.MAX_VALUE // 最大值 1.7976931348623157e+308
复制代码

如果超出则返回Infinity or -Infinity

也可以通过Number.NEGATIVE_INFINITY === -Infinity & Number.POSITIVE_INFINITY === Infinity 获取这两个值。

判断一个值是不是无穷值,可以通过isFinite

isFinite(Number.POSITIVE_INFINITY) // false
isFinite(1) // true
复制代码

NaN

NaN(Not a Number),表示本来要返回数值的操作失败了:

0/0 // NaN
5/0 // Infinity
5/-0 // -Infinity
复制代码

NaN和任何值比较都返回false哪怕是自身:

NaN === NaN //false
复制代码

判断一个值是否是 不是一个数字,可以通过isNaN

isNaN(NaN) // true
isNaN(10) // false
isNaN('10') // false
isNaN('aaa') // true
isNaN(true) // false
复制代码

NaN实现会调用对象的valueOf方法,然后确定返回的值是否可以转换成数值,如果不能,再调用toString方法,并测试其返回值。

数值转换

3个内置函数,将非数值转换为数值:

Number()
 + Number(true) ---> 1
 + Number(false) ---> 0
 + Number('') ---> 0
 + Number('1') ---> 1
 + Number('asd') ---> NaN
 + Number('0123') ---> 123
 + Number({}) ---> NaN
 + Number(new Number(1)) ---> 1
 + Number(undefined) ---> NaN
 + Number(null) ---> 0
 + Number(070) ---> 56
// Number传入对象时,会调用对象的valueOf方法
parseInt()
 + parseInt(true) ---> NaN
 + parseInt(false) ---> NaN
 + parseInt('') ---> NaN
 + parseInt('1') ---> 1
 + parseInt('0123') ---> 123
 + parseInt('asd') ---> NaN
 + parseInt(undefined) ---> NaN
 + parseInt(null) ---> NaN
 + parseInt(new Number(1)) ---> 1
 + parseInt(1.3) ---> 1
 + parseInt(1.9) ---> 1
 + parseInt('1.3') ---> 1
 + parseInt('11aa') ---> 11
 + patseInt('aa11') ---> NaN
// 不同的数值格式很容易混淆,因此parseInt也接受第二个参数,用于指定「进制数」
 + parseInt('0xAF', 16) ---> 175 // 按照16进制进行解析
 + parseInt('070', 8) ---> 56 // 按照8进制进行解析
 + parseInt('10', 10) ---> 10 // 按照10进制进行解析
 + parseInt('010', 2) ---> 2 // 按照2进制进行解析
 + parseInt('010') ---> 10 // 按照10进制进行解析
parseFloat()
 + parseFloat('1.2.3.4') ---> 1.2
 + parseFloat('0xAF') ---> 0
 + parseFloat("0908.5") ---> 908.5
 + parseFloat('3.998e7') ---> 39980000
// parseFloat与parseInt基本类似,float支持小数,解析到第一个小数点,后面再有小数点就不解析了,parseFloat只支持10进制
复制代码

String

字面量

字符串的3种字面量:

const age = '12'
const name = "HoMeTown"
const gender = `male`
复制代码

字符

  • \n 换行
  • \t 制表
  • \b 退格
  • \r 回车

特点

字符串一旦声明,就不能修改了。

let name = 'HoMeTown'
name[2] = 'O'
console.log(name) // HoMeTown
复制代码

转换为字符串

toString
true.toString() // true
let age = 1
age.toString() // 1 ()
let opt = {}
opt.toString() // [object Object]
null.toString() // null没有toString
String(null) // 'null'
undefined.toString() // undefined没有toString
String(undefined) // 'undefined'
Object.prototype.toString.call(true) // [object Boolean]
复制代码

toString一般情况下不接收参数,用在数值上的时候,可以传入一个「进制数」,得到该数值的x进制:

let num = 10; 
console.log(num.toString()); // "10"
console.log(num.toString(2)); // "1010"
console.log(num.toString(8)); // "12"
console.log(num.toString(10)); // "10"
console.log(num.toString(16)); // "a"
复制代码
模板字符串

将表达式转换为字符串时会调用

let foo = {
  name: 1,
  toString() {
    console.log("完了,我被调用了");
  },
};
let num = new Number(1);
num.toString = function () {
  console.log("数字对象");
  return "改一下";
};
const fooStr = `${foo}`;
const numStr = `${num}`;
console.log(numStr); // 改一下
复制代码

Symbol

Symbol 是原始值,并且是唯一的、不可变的。

let sym = Symbol();
console.log(typeof sym); // symbol
let firstSym = Symbol("hello");
let lastSym = Symbol("hello");
console.log(firstSym); // Symbol(hello)
console.log(lastSym); // Symbol(hello)
console.log(firstSym === lastSym); // false
//   let tryNewSym = new Symbol(); // Uncaught TypeError: Symbol is not a constructor
// 使用Symbol.for 可以使用之前创建过的symbol
let forSym1 = Symbol.for("hello");
let forSym2 = Symbol.for("hello");
console.log(forSym1); // Symbol(hello)
console.log(forSym2); // Symbol(hello)
console.log(forSym1 === forSym2); // true
// 使用Symbol.keyFor 可以查询全局注册表
console.log(Symbol.keyFor(forSym1)) // hello
console.log(Symbol.keyFor(forSym2)); // hello
复制代码

Symbol属性

定义对象属性:

const s1 = Symbol("msg");
const s2 = Symbol("gender");
const s3 = Symbol("name");
const s4 = Symbol("address");
let opt = {
  [s1]: "hello",
};
console.log(opt); // {Symbol(msg): 'hello'}
console.log(opt[s1]); // hello
Object.defineProperty(opt, s2, { value: "male" });
console.log(opt); // {Symbol(msg): 'hello', Symbol(gender): 'male'}Symbol(msg): "hello"Symbol(gender): "male"[[Prototype]]: Object
console.log(opt[s2]); // male
Object.defineProperties(opt, {
  [s3]: {
    value: "HoMeTown",
  },
  [s4]: {
    value: "北京",
  },
});
console.log(opt); // ...Symbol(name): HoMeTown, Symbol(address): 北京
复制代码

获取对象上的属性:

console.log(Object.getOwnPropertyNames(opt)); // ['id']
console.log(Object.getOwnPropertySymbols(opt)); // [Symbol(msg), Symbol(gender), Symbol(name), Symbol(address)]
console.log(Object.getOwnPropertyDescriptors(opt)); // {id: {…}, Symbol(msg): {…}, Symbol(gender): {…}, Symbol(name): {…}, Symbol(address): {…}}
console.log(Reflect.ownKeys(opt)); // ['id', Symbol(msg), Symbol(gender), Symbol(name), Symbol(address)]
复制代码

内置 Symbol符号

Symbol.hasInstance

instanceof 的原理就是Symbol.hasInstance,用来检测一个对象实例的原型上是否有原型:

class Foo {}
const foo = new Foo();
console.log(foo instanceof Foo); // true
复制代码

在ES6 中,instanceof 操作符会使用 Symbol.hasInstance 函数来确定关系。以 Symbol.

hasInstance 为键的函数会执行同样的操作,只是操作数对调了一下:

console.log(Foo[Symbol.hasInstance](foo)); // true
复制代码

这个属性定义在 Function 的原型上。因此默认在所有函数和类上都可以调用。由于 instanceof

操作符会在原型链上寻找这个属性定义,就跟在原型链上寻找其他属性一样,因此可以在继承的类上通过静态方法重新定义这个函数:

class Foo {
  static [Symbol.hasInstance]() {
    return false
  }
}
console.log(foo instanceof Foo); // false
复制代码

Object

对象其实就是一堆数据和功能的集合。

每个 Object 实例都有如下属性和方法。

  • constructor:用于创建当前对象的函数。在前面的例子中,这个属性的值就是 Object()函数。
  • hasOwnProperty(propertyName):用于判断当前对象实例(不是原型)上是否存在给定的属性。要检查的属性名必须是字符串(如 o.hasOwnProperty("name"))或符号。
  • isPrototypeOf(object):用于判断当前对象是否为另一个对象的原型。
  • propertyIsEnumerable(propertyName):用于判断给定的属性是否可以使用for-in 语句枚举。与 hasOwnProperty()一样,属性名必须是字符串。
  • toLocaleString():返回对象的字符串表示,该字符串反映对象所在的本地化执行环境。
  • toString():返回对象的字符串表示。
  • valueOf():返回对象对应的字符串、数值或布尔值表示。通常与 toString()的返回值相同。

总结

Js的数据类型:StringNumberNullUndefinedBolleanSymbolObject

目录
相关文章
|
7月前
|
JavaScript 前端开发 Java
JavaScript语言
JavaScript语言
40 1
|
1月前
|
JSON 前端开发 JavaScript
聊聊 Go 语言中的 JSON 序列化与 js 前端交互类型失真问题
在Web开发中,后端与前端的数据交换常使用JSON格式,但JavaScript的数字类型仅能安全处理-2^53到2^53间的整数,超出此范围会导致精度丢失。本文通过Go语言的`encoding/json`包,介绍如何通过将大整数以字符串形式序列化和反序列化,有效解决这一问题,确保前后端数据交换的准确性。
37 4
|
2月前
|
XML 监控 JavaScript
JavaScript 语言对企业上网监控的技术支持
在数字化企业环境中,上网监控对企业信息安全和提升员工效率至关重要。JavaScript 作为广泛应用的脚本语言,提供了强大的技术支持,包括数据获取与分析、与服务器端交互、监控页面加载时间和网络活动,助力企业有效管理上网行为,保障信息安全。
33 6
|
4月前
|
Web App开发 JavaScript 前端开发
Node.js与Go语言的对比?
【8月更文挑战第4天】Node.js与Go语言的对比?
416 3
|
4月前
|
自然语言处理 JavaScript 前端开发
【走向世界】Vue.js国际化:打造无国界应用,让爱与信息跨越语言的边界!
【8月更文挑战第30天】本文详细介绍了Vue.js中实现国际化的多种方法及最佳实践。通过使用`vue-i18n`等第三方库,开发者能够轻松地为应用添加多语言支持,优化用户体验并扩大市场覆盖范围。文章涵盖从基本配置、动态加载语言包到考虑文化差异等方面的内容,帮助读者构建真正全球化且无缝多语言体验的应用程序。
128 0
|
4月前
|
JavaScript 前端开发 UED
探索JavaScript的历史:网络需求初现、语言创立与标准化的旅程
探索JavaScript的历史:网络需求初现、语言创立与标准化的旅程
|
6月前
|
JavaScript 前端开发 编译器
ECMAScript与JavaScript:一场语言的邂逅
ECMAScript与JavaScript:一场语言的邂逅
|
7月前
|
JavaScript 测试技术
【sgGoogleTranslate】自定义组件:基于Vue.js用谷歌Google Translate翻译插件实现网站多国语言开发
【sgGoogleTranslate】自定义组件:基于Vue.js用谷歌Google Translate翻译插件实现网站多国语言开发
|
6月前
|
JavaScript Java 测试技术
基于springboot+vue.js+uniapp小程序的java语言的考试信息报名系统附带文章源码部署视频讲解等
基于springboot+vue.js+uniapp小程序的java语言的考试信息报名系统附带文章源码部署视频讲解等
57 0
|
7月前
|
JavaScript 前端开发 Java
javascript是弱类型语言,一个函数参数可以接收不同类型的变量作为它的该参数
javascript是弱类型语言,一个函数参数可以接收不同类型的变量作为它的该参数
61 0