JS一些输出是什么

1. 暂时性死区

通过 letconst 关键字声明的变量也会提升,但是和 var 不同,它们不会被初始化。在我们声明(初始化)之前是不能访问它们的。这个行为被称之为 暂时性死区。当我们试图在声明之前访问它们时,JavaScript 将会抛出一个 ReferenceError 错误。

function sayHi() {
	console.log(name);	// undefined
	console.log(age);	// Uncaught ReferenceError: Cannot access 'age' before initialization
	var name = 'Lydia';
	let age = 20;
}

2. 箭头函数的this

对于箭头函数,this 关键字指向的是它 当前周围作用域(简单来说是包含箭头函数的常规函数,如果没有常规函数的话就是全局对象),这个行为和常规函数不同。

const shape = {
  radius: 10,
  diameter() {
    return this.radius * 2
  },
  perimeter: () => 2 * Math.PI * this.radius
}

shape.diameter()	// 20 常规函数,this就是shape
shape.perimeter()	// NaN 周围作用域window,没有radius,返回undefined

3. 一元运算符

一元操作符加号尝试将 boolean 转为 number

+true	// 1
!"Lydia"	// false

4. new 一个 Number

new Number() 是一个内建的函数构造器。虽然它看着像是一个 number,但它实际上并不是一个真实的 number:它有一堆额外的功能并且它是一个对象。

let a = 3
let b = new Number(3)	// Number {3}
let c = 3

console.log(a == b)		// true
console.log(a === b)	// false
console.log(b === c)	// false

当我们使用 == 操作符时,它只会检查两者是否拥有相同的值。因为它们的值都是 3,因此返回 true。

当我们使用 === 操作符时,两者的值以及类型都应该是相同的。new Number() 是一个对象而不是 number,因此返回 false。

5. 类的静态方法

静态方法被设计为只能被创建它们的构造器使用,并且不能传递给实例:

class Chameleon {
  static colorChange(newColor) {
    this.newColor = newColor
    return this.newColor
  }

  constructor({ newColor = 'green' } = {}) {
    this.newColor = newColor
  }
}

const freddie = new Chameleon({ newColor: 'purple' })
freddie.colorChange('orange')	// TypeError: freddie.colorChange is not a function
  • 通过关键字 static 定义静态方法 colorChange。
  • 直接通过类调用静态方法,而不是对象实例调用。
  • freddie.colorChange 之所以会报错,它是调用的实例方法colorChange ,然而并没有定义。

6. 给构造函数添加属性

不能像常规对象那样,给构造函数添加属性。如果你想一次性给所有实例添加特性,你应该使用原型。

function Person(firstName, lastName) {
  this.firstName = firstName;
  this.lastName = lastName;
}

const member = new Person("Lydia", "Hallie");
Person.getFullName = function () {
  return `${this.firstName} ${this.lastName}`;
}

console.log(member.getFullName());	// 报错,member.getFullName is not a function

为什么这样设计?
假设我们将这个方法添加到构造函数本身里。也许不是每个 Person 实例都需要这个方法。这将浪费大量内存空间,因为它们仍然具有该属性,这将占用每个实例的内存空间。相反,如果我们只将它添加到原型中,那么它只存在于内存中的一个位置,但是所有实例都可以访问它!

7. 使用new和不使用的区别

function Person(firstName, lastName) {
  this.firstName = firstName
  this.lastName = lastName
}

const lydia = new Person('Lydia', 'Hallie')
const sarah = Person('Sarah', 'Smith')

console.log(lydia)	// Person {firstName: "Lydia", lastName: "Hallie"}
console.log(sarah)	// undefined

对于 sarah,我们没有使用 new 关键字。当使用 new 时,this 引用我们创建的空对象。当未使用 new 时,this 引用的是全局对象(global object)。

我们说 this.firstName 等于 “Sarah”,并且 this.lastName 等于 “Smith”。实际上我们做的是,定义了 global.firstName = ‘Sarah’ 和 global.lastName = ‘Smith’。而 sarah 本身是 undefined。

8. 标记模板字面量

如果使用标记模板字面量,第一个参数的值总是包含字符串的数组。其余的参数获取的是传递的表达式的值:

function getPersonInfo(one, two, three) {
  console.log(one)	// ["", " is ", " years old", raw: Array(3)]
  console.log(two)	// Lydia
  console.log(three)	// 21
}

const person = 'Lydia'
const age = 21

getPersonInfo`${person} is ${age} years old`

9. 对象的键

所有对象的键(不包括 Symbol)在底层都是字符串,即使你自己没有将其作为字符串输入。

const obj = { 1: 'a', 2: 'b', 3: 'c' }
const set = new Set([1, 2, 3, 4, 5])

obj.hasOwnProperty('1')		// true
obj.hasOwnProperty(1)		// true
set.has('1')				// false
set.has(1)					// true

对于集合,它不是这样工作的。在我们的集合中没有 ‘1’:set.has(‘1’) 返回 false。它有数字类型为 1,set.has(1) 返回 true。

10. 生成器函数

一般的函数在执行之后是不能中途停下的。但是,生成器函数却可以中途“停下”,之后可以再从停下的地方继续。当生成器遇到 yield 关键字的时候,会生成 yield 后面的值。注意,生成器在这种情况下不 返回 (return ) 值,而是 生成 (yield) 值。

function* generator(i) {
  yield i;
  yield i * 2;
}

const gen = generator(10);

console.log(gen.next().value);	// 10
console.log(gen.next().value);	// 20

代码解析:
首先,我们用10作为参数i来初始化生成器函数。然后使用next()方法一步步执行生成器。第一次执行生成器的时候,i的值为10,遇到第一个yield关键字,它要生成i的值。此时,生成器“暂停”,生成了10。

然后,我们再执行next()方法。生成器会从刚才暂停的地方继续,这个时候i还是10。于是我们走到了第二个yield关键字处,这时候需要生成的值是i*2,i为10,那么此时生成的值便是20。所以这道题的最终结果是10,20。

11. parseInt解析

parseInt只返回了字符串中第一个字母. 设定了 进制 后 (也就是第二个参数,指定需要解析的数字是什么进制: 十进制、十六机制、八进制、二进制等等……),parseInt 检查字符串中的字符是否合法. 一旦遇到一个在指定进制中不合法的字符后,立即停止解析并且忽略后面所有的字符。

const num = parseInt("7*6", 10);	// 7

*就是不合法的数字字符。所以只解析到"7",并将其解析为十进制的7. num的值即为7.

12. delete操作符

delete 操作符返回一个 布尔值: true指删除成功,否则返回false. 但是通过 var, constlet 关键字声明的变量无法用 delete 操作符来删除。

const name = "Lydia";
age = 21;

console.log(delete name);	// false
console.log(delete age);	// true

name 变量由 const 关键字声明,所以删除不成功:返回 false. 而我们设定age等于21时,我们实际上添加了一个名为age的属性给全局对象。对象中的属性是可以删除的,全局对象也是如此,所以 delete age 返回 true。

13. Object.defineProperty

const person = { name: "Lydia" };

Object.defineProperty(person, "age", { value: 21 });

console.log(person);	// { name: "Lydia", age: 21 }
console.log(Object.keys(person));	// ["name"]

通过 defineProperty 方法,我们可以给对象添加一个新属性,或者修改已经存在的属性。而我们使用 defineProperty 方法给对象添加了一个属性之后,属性默认为 不可枚举(not enumerable). Object.keys 方法仅返回对象中 可枚举(enumerable) 的属性,因此只剩下了 “name”.

defineProperty 方法添加的属性默认不可变。你可以通过 writable, configurable 和 enumerable 属性来改变这一行为。这样的话, 相比于自己添加的属性,defineProperty 方法添加的属性有了更多的控制权。

14. JSON.stringify第二个参数

const settings = {
  username: "lydiahallie",
  level: 19,
  health: 90
};

const data = JSON.stringify(settings, ["level", "health"]);
console.log(data);	// "{"level":19, "health":90}"

JSON.stringify 的第二个参数是 替代者(replacer). 替代者(replacer)可以是个函数或数组,用以控制哪些值如何被转换为字符串。

如果替代者(replacer)是个 数组 ,那么就只有包含在数组中的属性将会被转化为字符串。在本例中,只有名为"level" 和 “health” 的属性被包括进来, "username"则被排除在外。 data 就等于 “{“level”:19, “health”:90}”.

而如果替代者(replacer)是个 函数,这个函数将被对象的每个属性都调用一遍。 函数返回的值会成为这个属性的值,最终体现在转化后的JSON字符串中(译者注:Chrome下,经过实验,如果所有属性均返回同一个值的时候有异常,会直接将返回值作为结果输出而不会输出JSON字符串),而如果返回值为undefined,则该属性会被排除在外。

15. padStartf方法

使用padStart方法,我们可以在字符串的开头添加填充。传递给此方法的参数是字符串的总长度(包含填充)。
如果传递给padStart方法的参数小于字符串的长度,则不会添加填充。

const name = "Lydia Hallie"
console.log(name.padStart(13))	// " Lydia Hallie"
console.log(name.padStart(2))	// "Lydia Hallie"

字符串Lydia Hallie的长度为12, 因此name.padStart(13)在字符串的开头只会插入1(13 - 12 = 1)个空格。

16. 函数的prototype

常规函数,例如giveLydiaPizza函数,有一个prototype属性,它是一个带有constructor属性的对象(原型对象)。 然而,箭头函数,例如giveLydiaChocolate函数,没有这个prototype属性。 尝试使用giveLydiaChocolate.prototype访问prototype属性时会返回undefined。

function giveLydiaPizza() {
  return "Here is pizza!"
}

const giveLydiaChocolate = () => "Here's chocolate... now go hit the gym already."

console.log(giveLydiaPizza.prototype)	// {constructor: ...}
console.log(giveLydiaChocolate.prototype)	// undefined

17. Object.entries

Object.entries()方法返回一个给定对象自身可枚举属性的键值对数组,下述情况返回一个二维数组,数组每个元素是一个包含键和值的数组:
[['name','Lydia'],['age',21]]

const person = {
  name: "Lydia",
  age: 21
}

for (const [x, y] of Object.entries(person)) {
  console.log(x, y)	// name Lydia and age 21
}

使用for-of循环,我们可以迭代数组中的每个元素,上述情况是子数组。 我们可以使用const [x,y]在for-of循环中解构子数组。 x等于子数组中的第一个元素,y等于子数组中的第二个元素。

第一个子阵列是[“name”,“Lydia”],其中x等于name,而y等于Lydia。 第二个子阵列是[“age”,21],其中x等于age,而y等于21。

18. 箭头函数返回值

对于箭头函数,如果只返回一个值,我们不必编写花括号。但是,如果您想从一个箭头函数返回一个对象,您必须在圆括号之间编写它,否则不会返回任何值:

const getList = ([x, ...y]) => [x, y]
const getUser = user => { name: user.name, age: user.age }

const list = [1, 2, 3, 4]
const user = { name: "Lydia", age: 21 }

console.log(getList(list))	// [1, [2, 3, 4]]
console.log(getUser(user))	// undefined

const getUser = user => ({ name: user.name, age: user.age })	// { name: "Lydia", age: 21 }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值