我们在看编写的JS ES6代码时经常会看到许多简写的语法,写的十分的全面细致,具有一定的参考价值,对此有需要的朋友可以参考学习下。如有不足之处,欢迎批评指正。

ES6为一些已有的功能提供了非破坏性更新,这类更新中的大部分我们可以理解为语法糖,称之为语法糖,意味着,这类新语法能做的事情其实用ES5也可以做,只是会稍微复杂一些。本章我们将着重讨论这些语法糖,看完之后,可能你会对一些你很熟悉的ES6新语法有不一样的理解。

JavaScript ES6对象字面量

对象字面量是指以{}形式直接表示的对象,比如下面这样:

var book = {title: 'Modular ES6',author: 'Nicolas',publisher: 'O´Reilly'
}

ES6 为对象字面量的语法带来了一些改进:包括属性/方法的简洁表示,可计算的属性名等等,我们逐一来看:

JavaScript ES6中属性的简洁表示法

你有没有遇到过这种场景,一个我们声明的对象中包含若干属性,其属性值由变量表示,且变量名和属性名一样的。比如下面这样,我们想把一个名为 listeners 的数组赋值给events对象中的listeners属性,用ES5我们会这样做:

var listeners = []
function listen() {}
var events = {listeners: listeners,listen: listen
}

ES6则允许我们简写成下面这种形式:

var listeners = []
function listen() {}
var events = { listeners, listen }

怎么样,是不是感觉简洁了许多,使用对象字面量的简洁写法让我们在不影响语义的情况下减少了重复代码。
这是ES6带来的好处之一,它提供了众多更简洁,语义更清晰的语法,让我们的代码的可读性,可维护性大大提升。

可计算的属性名

对象字面量的另一个重要更新是允许你使用可计算的属性名,在ES5中我们也可以给对象添加属性名为变量的属性,一般说来,我们要按下面方法这样做,首先声明一个名为expertise的变量,然后通过person[expertise]这种形式把变量添加为对象person的属性:

var expertise = 'journalism'
var person = {name: 'Sharon',age: 27
}
person[expertise] = {years: 5,interests: ['international', 'politics', 'internet']
}//在此我向大家推荐一个前端全栈开发交流圈:619586920  突破技术瓶颈,提升思维能力

ES6 中,对象字面量可以使用计算属性名了,把任何表达式放在中括号中,表达式的运算结果将会是对应的属性名,上面的代码,用ES6可以这样写:

var expertise = 'journalism'
var person = {name: 'Sharon',age: 27,[expertise]: {years: 5,interests: ['international', 'politics', 'internet']}
}//在此我向大家推荐一个前端全栈开发交流圈:619586920  突破技术瓶颈,提升思维能力

不过需要注意的是,简写属性和计算的属性名不可同时使用。这是因为,简写属性是一种在编译阶段的就会生效的语法糖,而计算的属性名则在运行时才生效。如果你把二者混用,代码会报错。而且二者混用往往还会降低代码的可读性,所以JavaScript在语言层面上限制二者不能混用也是个好事。

var expertise = 'journalism'
var journalism = {years: 5,interests: ['international', 'politics', 'internet']
}
var person = {name: 'Sharon',age: 27,[expertise] // 这里会报语法错误
}

遇到以下情景时,可计算的属性名会让我们的代码更简洁:
某个新对象的属性引自另一个对象:

var grocery = {id: 'bananas',name: 'Bananas',units: 6,price: 10,currency: 'USD'
}
var groceries = {[grocery.id]: grocery
}//在此我向大家推荐一个前端全栈开发交流圈:619586920  突破技术瓶颈,提升思维能力

需构建的对象的属性名来自函数参数。如果使用ES5来处理这种问题,我们需要先声明一个对象字面量,再动态的添加属性,再返回这个对象。下面的例子中,我们创建了一个响应Ajax请求的函数,这个函数的作用在于,请求失败时,返回的对象拥有一个名为error属性及对应的描述,请求成功时,该对象拥有一个名为success属性及对应的描述。

// ES5 写法
function getEnvelope(type, description) {var envelope = {data: {}}envelope[type] = descriptionreturn envelope
}

使用ES6提供的利用计算属性名,更简洁的实现如下:

// ES6 写法
function getEnvelope(type, description) {return {data: {},[type]: description}
}

对象字面量的属性可以简写,方法其实也是可以的。

JavaScript ES6方法定义

我们先看看传统上如何定义对象方法,下述代码中,我们构建了一个事件发生器,其中的on方法用以注册事件,emit方法用以执行事件:

var emitter = {events: {},on: function (type, fn) {if (this.events[type] === undefined) {this.events[type] = []}this.events[type].push(fn)},emit: function (type, event) {if (this.events[type] === undefined) {return}this.events[type].forEach(function (fn) {fn(event)})}
}//在此我向大家推荐一个前端全栈开发交流圈:619586920  突破技术瓶颈,提升思维能力

ES6 的对象字面量方法简写允许我们省略对象方法的function关键字及之后的冒号,改写后的代码如下:

var emitter = {events: {},on(type, fn) {if (this.events[type] === undefined) {this.events[type] = []}this.events[type].push(fn)},emit(type, event) {if (this.events[type] === undefined) {return}this.events[type].forEach(function (fn) {fn(event)})//在此我向大家推荐一个前端全栈开发交流圈:619586920  突破技术瓶颈,提升思维能力}
}

ES6中的箭头函数可谓大名鼎鼎了,它有一些特别的优点(关于this),可能你和我一样,使用箭头函数很久了,不过有些细节我之前却一直不了解,比如箭头函数的几种简写形式及使用注意事项。

JavaScript ES6箭头函数

JS中声明的普通函数,一般有函数名,一系列参数和函数体,如下:

function name(parameters) {// function body
}

普通匿名函数则没有函数名,匿名函数通常会被赋值给一个变量/属性,有时候还会被直接调用:

var example = function (parameters) {// function body
}

ES6 为我们提供了一种写匿名函数的新方法,即箭头函数。箭头函数不需要使用function关键字,其参数和函数体之间以=>相连接:

var example = (parameters) => {// function body
}

尽管箭头函数看起来类似于传统的匿名函数,他们却具有根本性的不同:

  • 箭头函数不能被直接命名,不过允许它们赋值给一个变量;
  • 箭头函数不能用做构造函数,你不能对箭头函数使用new关键字;
  • 箭头函数也没有prototype属性;
  • 箭头函数绑定了词法作用域,不会修改this的指向。
  • 最后一点是箭头函数最大的特点,我们来仔细看看。

词法作用域

我们在箭头函数的函数体内使用的this,arguments,super等都指向包含箭头函数的上下文,箭头函数本身不产生新的上下文。下述代码中,我们创建了一个名为timer的对象,它的属性seconds用以计时,方法start用以开始计时,若我们在若干秒后调用start方法,将打印出当前的seconds值。

// ES5
var timer = {seconds: 0,start() {setInterval(function(){this.seconds++}, 1000)}
}timer.start()
setTimeout(function () {console.log(timer.seconds)
}, 3500)
//在此我向大家推荐一个前端全栈开发交流圈:619586920  突破技术瓶颈,提升思维能力 
> 0
// ES6
var timer = {seconds: 0,start() {setInterval(() => {this.seconds++}, 1000)}
}timer.start()
setTimeout(function () {console.log(timer.seconds)
}, 3500)
// <- 3

第一段代码中start方法使用的是常规的匿名函数定义,在调用时this将指向了window,console出的结果为undefined,想要让代码正常工作,我们需要在start方法开头处插入var self = this,然后替换匿名函数函数体中的this为self,第二段代码中,我们使用了箭头函数,就不会发生这种情况了。
还需要说明的是,箭头函数的作用域也不能通过.call,.apply,.bind等语法来改变,这使得箭头函数的上下文将永久不变。
我们再来看另外一个箭头函数与普通匿名函数的不同之处,你猜猜,下面的代码最终打印出的结果会是什么:

function puzzle() {return function () {console.log(arguments)}
}
puzzle('a', 'b', 'c')(1, 2, 3)

答案是1,2,3,原因是对常规匿名函数而言,arguments指向匿名函数本身。
作为对比,我们看看下面这个例子,再猜猜,打印结果会是什么?

function puzzle() {return ()=>{console.log(arguments)}
}
puzzle('a', 'b', 'c')(1, 2, 3)

答案是a,b,c,箭头函数的特殊性决定其本身没有arguments对象,这里的arguments其实是其父函数puzzle的。
前面我们提到过,箭头函数还可以简写,接下来我们一起看看。

简写的箭头函数

完整的箭头函数是这样的:

var example = (parameters) => {// function body
}

简写1:
当只有一个参数时,我们可以省略箭头函数参数两侧的括号:

var double = value => {return value * 2
}

简写2:
对只有单行表达式且,该表达式的值为返回值的箭头函数来说,表征函数体的{},可以省略,return 关键字可以省略,会静默返回该单一表达式的值。

var double = (value) => value * 2

简写3:
上述两种形式可以合并使用,而得到更加简洁的形式

var double = value => value * 2

现在,你肯定学会了箭头函数的基本使用方法,接下来我们再看几个使用示例。

简写箭头函数带来的一些问题

当你的简写箭头函数返回值为一个对象时,你需要用小括号括起你想返回的对象。否则,浏览器会把对象的{}解析为箭头函数函数体的开始和结束标记。

// 正确的使用形式
var objectFactory = () => ({ modular: 'es6' })

下面的代码会报错,箭头函数会把本想返回的对象的花括号解析为函数体,number被解析为label,value解释为没有做任何事情表达式,我们又没有显式使用return,返回值默认是undefined。
[1, 2, 3].map(value => { number: value })
// <- [undefined, undefined, undefined]
当我们返回的对象字面量不止一个属性时,浏览器编译器不能正确解析第二个属性,这时会抛出语法错误。
//在此我向大家推荐一个前端全栈开发交流圈:619586920 突破技术瓶颈,提升思维能力

[1, 2, 3].map(value => { number: value, verified: true })
// <- SyntaxError

解决方案是把返回的对象字面量包裹在小括号中,以助于浏览器正确解析:

[1, 2, 3].map(value => ({ number: value, verified: true }))
/* <- [{ number: 1, verified: true },{ number: 2, verified: true },{ number: 3, verified: true }]
*/

该何时使用箭头函数

其实我们并不应该盲目的在一切地方使用ES6,ES6也不是一定比ES5要好,是否使用主要看其能否改善代码的可读性和可维护性。
箭头函数也并非适用于所有的情况,比如说,对于一个行数很多的复杂函数,使用=>代替function关键字带来的简洁性并不明显。不过不得不说,对于简单函数,箭头函数确实能让我们的代码更简洁。
给函数以合理的命名,有助于增强程序的可读性。箭头函数并不能直接命名,但是却可以通过赋值给变量的形式实现间接命名,如下代码中,我们把箭头函数赋值给变量 throwError,当函数被调用时,会抛出错误,我们可以追溯到是箭头函数throwError报的错。

var throwError = message => {throw new Error(message)
}
throwError('this is a warning')
<- Uncaught Error: this is a warningat throwError

如果你想完全控制你的函数中的this,使用箭头函数是简洁高效的,采用函数式编程尤其如此。

[1, 2, 3, 4].map(value => value * 2).filter(value => value > 2).forEach(value => console.log(value))
// <- 4
// <- 6
// <- 8

解构赋值

ES6提供的最灵活和富于表现性的新特性莫过于解构了。一旦你熟悉了,它用起来也很简单,某种程度上解构可以看做是变量赋值的语法糖,可应用于对象,数组甚至函数的参数。

对象解构

为了更好的描述对象解构如何使用,我们先构建下面这样一个对象(漫威迷一定知道这个对象描述的是谁):

// 描述Bruce Wayne的对象
var character = {name: 'Bruce',pseudonym: 'Batman',metadata: {age: 34,gender: 'male'},batarang: ['gas pellet', 'bat-mobile control', 'bat-cuffs']
}

假如现有有一个名为 pseudonym 的变量,我们想让其变量值指向character.pseudonym,使用ES5,你往往会按下面这样做:

var pseudonym = character.pseudonym

ES6致力于让我们的代码更简洁,通过ES6我们可以用下面的代码实现一样的功能:

var { pseudonym } = character

如同你可以使用var加逗号在一行中同时声明多个变量,解构的花括号内使用逗号可以做一样的事情。

var { pseudonym, name } = character

我们还可以混用解构和常规的自定义变量,这也是解构语法灵活性的表现之一。

var { pseudonym } = character, two = 2

解构还允许我们使用别名,比如我们想把character.pseudonym赋值给变量 alias,可以按下面的语句这样做,只需要在pseudonym后面加上:即可:

var { pseudonym: alias } = character
console.log(alias)
// <- 'Batman'

解构还有另外一个强大的功能,解构值还可以是对象:

var { metadata: { gender } } = character

当然,对于多层解构,我们同样可以赋予别名,这样我们可以通过非常简洁的方法修改子属性的名称:

var { metadata: { gender: characterGender } } = character

在ES5 中,当你调用一个未曾声明的值时,你会得到undefined:

console.log(character.boots)
// <- undefined
console.log(character['boots'])
// <- undefined

使用解构,情况也是类似的,如果你在左边声明了一个右边对象中不存在的属性,你也会得到undefined.

var { boots } = character
console.log(boots)
// <- undefined

对于多层解构,如下述代码中,boots并不存在于character中,这时程序会抛出异常,这就好比你你调用undefined或者null的属性时会出现异常。

var { boots: { size } } = character
// <- Exception
var { missing } = null
// <- Exception

解构其实就是一种语法糖,看以下代码,你肯定就能很快理解为什么会抛出异常了。

var nothing = null
var missing = nothing.missing
// <- Exception

解构也可以添加默认值,如果右侧不存在对应的值,默认值就会生效,添加的默认值可以是数值,字符串,函数,对象,也可以是某一个已经存在的变量:

var { boots = { size: 10 } } = character
console.log(boots)
// <- { size: 10 }

对于多层的解构,同样可以使用默认值

var { metadata: { enemy = 'Satan' } } = character
console.log(enemy)
// <- 'Satan'

默认值和别名也可以一起使用,不过需要注意的是别名要放在前面,默认值添加给别名:

var { boots: footwear = { size: 10 } } = character

对象解构同样支持计算属性名,但是这时候你必须要添加别名,这是因为计算属性名允许任何类似的表达式,不添加别名,浏览器解析时会有问题,使用如下:

var { ['boo' + 'ts']: characterBoots } = character
console.log(characterBoots)
// <- true

还是那句话,我们也不是任何情况下都应该使用解构,语句characterBoots = character[type]看起来比{ [type]: characterBoots } = character语义更清晰,但是当你需要提取对象中的子对象时,解构就很简洁方便了。
我们再看看在数组中该如何使用解构。

数组解构

数组解构的语法和对象解构是类似的。区别在于,数组解构我们使用中括号而非花括号,下面的代码中,通过结构,我们在数组coordinates中提出了变量 x,y 。 你不需要使用x = coordinates[0]这样的语法了,数组解构不使用索引值,但却让你的代码更加清晰。

var coordinates = [12, -7]
var [x, y] = coordinates
console.log(x)
// <- 12

数组解构也允许你跳过你不想用到的值,在对应地方留白即可:

var names = ['James', 'L.', 'Howlett']
var [ firstName, , lastName ] = names
console.log(lastName)
// <- 'Howlett'

和对象解构一样,数组解构也允许你添加默认值:

var names = ['James', 'L.']
var [ firstName = 'John', , lastName = 'Doe' ] = names
console.log(lastName)
// <- 'Doe'
//在此我向大家推荐一个前端全栈开发交流圈:619586920  突破技术瓶颈,提升思维能力

在ES5中,你需要借助第三个变量,才能完成两个变量值的交换,如下:

var left = 5, right = 7;
var aux = left
left = right
right = aux

使用解构,一切就简单多了:

var left = 5, right = 7;
[left, right] = [right, left]

我们再看看函数解构。
函数默认参数
在ES6中,我们可以给函数的参数添加默认值了,下例中我们就给参数 exponent 分配了一个默认值:

function powerOf(base, exponent = 2) {return Math.pow(base, exponent)
}

箭头函数同样支持使用默认值,需要注意的是,就算只有一个参数,如果要给参数添加默认值,参数部分一定要用小括号括起来。

var double = (input = 0) => input * 2

我们可以给任何位置的任何参数添加默认值。

function sumOf(a = 1, b = 2, c = 3) {return a + b + c
}console.log(sumOf(undefined, undefined, 4))
// <- 1 + 2 + 4 = 7

在JS中,给一个函数提供一个包含若干属性的对象字面量做为参数的情况并不常见,不过你依旧可以按下面方法这样做:

var defaultOptions = { brand: 'Volkswagen', make: 1999 }
function carFactory(options = defaultOptions) {console.log(options.brand)console.log(options.make)
}//在此我向大家推荐一个前端全栈开发交流圈:619586920  突破技术瓶颈,提升思维能力
carFactory()
// <- 'Volkswagen'
// <- 1999

不过这样做存在一定的问题,当你调用该函数时,如果传入的参数对象只包含一个属性,另一个属性的默认值会自动失效:

carFactory({ make: 2000 })
// <- undefined
// <- 2000

函数参数解构就可以解决这个问题。

函数参数解构

通过函数参数解构,可以解决上面的问题,这里我们为每一个属性都提供了默认值,单独改变其中一个并不会影响其它的值:

function carFactory({ brand = 'Volkswagen', make = 1999 }) {console.log(brand)console.log(make)
}
carFactory({ make: 2000 })
// <- 'Volkswagen'
// <- 2000

不过这种情况下,函数调用时,如果参数为空即carFactory()函数将抛出异常。这种问题可以通过下面的方法来修复,下述代码中我们添加了一个空对象作为options的默认值,这样当函数被调用时,如果参数为空,会自动以{}作为参数。

function carFactory({brand = 'Volkswagen',make = 1999
} = {}) {console.log(brand)console.log(make)
}
carFactory()
// <- 'Volkswagen'
// <- 1999

除此之外,使用函数参数解构,还可以让你的函数自行匹配对应的参数,看接下来的例子,你就能明白这一点了,我们定义一个名为car的对象,这个对象拥有很多属性:owner,brand,make,model,preferences等等。

var car = {owner: {id: 'e2c3503a4181968c',name: 'Donald Draper'},brand: 'Peugeot',make: 2015,model: '208',preferences: {airbags: true,airconditioning: false,color: 'red'}
}

解构能让我们的函数方便的只使用里面的部分数据,下面代码中的函数getCarProductModel说明了具体该如何使用:

var getCarProductModel = ({ brand, make, model }) => ({sku: brand + ':' + make + ':' + model,brand,make,model
})
getCarProductModel(car)

解构使用示例

当一个函数的返回值为对象或者数组时,使用解构,我们可以非常简洁的获取返回对象中某个属性的值(返回数组中某一项的值)。比如说,函数getCoordinates()返回了一系列的值,但是我们只想用其中的x,y,我们可以这样写,解构帮助我们避免了很多中间变量的使用,也使得我们代码的可读性更高。

function getCoordinates() {return { x: 10, y: 22, z: -1, type: '3d' }
}
var { x, y } = getCoordinates()

通过使用默认值,可以减少重复,比如你想写一个random函数,这个函数将返回一个位于min和max之间的值。我们可以分辨设置min默认值为1,max默认值为10,在需要的时候还可以单独改变其中的某一个值:

function random({ min = 1, max = 10 } = {}) {return Math.floor(Math.random() * (max - min)) + min
}//在此我向大家推荐一个前端全栈开发交流圈:619586920  突破技术瓶颈,提升思维能力
console.log(random())
// <- 7
console.log(random({ max: 24 }))
// <- 18

解构还可以配合正则表达式使用。看下面这个例子:

function splitDate(date) {var rdate = /(\d+).(\d+).(\d+)/return rdate.exec(date)
}
var [ , year, month, day] = splitDate('2015-11-06')

不过当.exec不比配时会返回null,因此我们需要修改上述代码如下:

var matches = splitDate('2015-11-06')
if (matches === null) {return
}
var [, year, month, day] = matches

下面我们继续来讲讲spread和rest操作符。

剩余参数和拓展符

ES6之前,对于不确定数量参数的函数。你需要使用伪数组arguments,它拥有length属性,却又不具备很多一般数组有的特性。需要通过Array#slice.call转换arguments对象真数组后才能进行下一步的操作:

function join() {var list = Array.prototype.slice.call(arguments)return list.join(', ')
}
join('first', 'second', 'third')
// <- 'first, second, third'

对于这种情况,ES6提供了一种更好的解决方案:rest。

剩余参数rest

使用rest, 你只需要在任意JavaScript函数的最后一个参数前添加三个点…即可。当rest参数是函数的唯一参数时,它就代表了传递给这个函数的所有参数。它起到和前面说的.slice一样的作用,把参数转换为了数组,不需要你再对arguments进行额外的转换了。

function join(...list) {return list.join(', ')
}
join('first', 'second', 'third')
// <- 'first, second, third'

rest参数之前的命名参数不会被包含在rest中,

function join(separator, ...list) {return list.join(separator)
}
join('; ', 'first', 'second', 'third')
// <- 'first; second; third'

在箭头函数中使用rest参数时,即使只有这一个参数,也需要使用圆括号把它围起来,不然就会报错SyntaxError,使用示例如下:

var sumAll = (...numbers) => numbers.reduce((total, next) => total + next
)//在此我向大家推荐一个前端全栈开发交流圈:619586920  突破技术瓶颈,提升思维能力
console.log(sumAll(1, 2, 5))
// <- 8

上述代码的ES5实现如下:

// ES5的写法
function sumAll() {var numbers = Array.prototype.slice.call(arguments)return numbers.reduce(function (total, next) {return total + next})
}
console.log(sumAll(1, 2, 5))
// <- 8

拓展运算符

拓展运算符可以把任意可枚举对象转换为数组,使用拓展运算符可以高效处理目标对象,在拓展目前前添加…就可以使用拓展运算符了。下例中…arguments就把函数的参数转换为了数组字面量。

function cast() {return [...arguments]
}
cast('a', 'b', 'c')
// <- ['a', 'b', 'c']

使用拓展运算符,我们也可以把字符串转换为由每一个字母组成的数组:

[...'show me']
// <- ['s', 'h', 'o', 'w', ' ', 'm', 'e']

使用拓展运算符,还可以拼合数组:

function cast() {return ['left', ...arguments, 'right']
}
cast('a', 'b', 'c')
// <- ['left', 'a', 'b', 'c', 'right']
var all = [1, ...[2, 3], 4, ...[5], 6, 7]
console.log(all)
// <- [1, 2, 3, 4, 5, 6, 7]

这里我还想再强调一下,拓展运算符不仅仅适用于数组和arguments对象,对任意可迭代的对象都可以使用。迭代也是ES6新提出的一个概念,在 Iteration and Flow Control这一章,我们将详细叙述迭代。
Shifting和Spreading

当你想要抽出一个数组的前一个或者两个元素时,常用的解决方案是使用.shift.尽管是函数式的,下述代码在第一次看到的时候却不好理解,我们使用了两次.slice从list中抽离出两个不同的元素。

var list = ['a', 'b', 'c', 'd', 'e']
var first = list.shift()
var second = list.shift()
console.log(first)
// <- 'a'

在ES6中,结合使用拓展和解构,可以让代码的可读性更好:

var [first, second, ...other] = ['a', 'b', 'c', 'd', 'e']
console.log(other)
// <- ['c', 'd', 'e']

除了对数组进行拓展,你同样可以对函数参数使用拓展,下例展示了如何添加任意数量的参数到multiply函数中。

function multiply(left, right) {return left * right
}
var result = multiply(...[2, 3])
console.log(result)
// <- 6

向在数组中一样,函数参数中的拓展运算符同样可以结合常规参数一起使用。下例中,print函数结合使用了rest,普通参数,和拓展运算符:

function print(...list) {console.log(list)
}
print(1, ...[2, 3], 4, ...[5])
// <- [1, 2, 3, 4, 5]

下表总结了,拓展运算符的常见使用方法:

使用示例 ES5 ES6

Concatenation [1, 2].concat(more) [1, 2, …more]
Push an array onto list list.push.apply(list, items) list.push(…items)
Destructuring a = list[0], other = list.slice(1) [a, …other] = list
new and apply new (Date.bind.apply(Date, [null,2015,31,8])) new Date(…[2015,31,8])

模板字符串

模板字符串是对常规JavaScript字符串的重大改进,不同于在普通字符串中使用单引号或者双引号,模板字符串的声明需要使用反撇号,如下所示:

var text = `This is my first template literal`

因为使用的是反撇号,你可以在模板字符串中随意使用单双引号了,使用时不再需要考虑转义,如下:

var text = `I'm "amazed" at these opportunities!`

模板字符串具有很多强大的功能,可在其中插入JavaScript表达式就是其一。

在字符串中插值

通过模板字符串,你可以在模板中插入任何JavaScript表达式了。当解析到表达式时,表达式会被执行,该处将渲染表达式的值,下例中,我们在字符串中插入了变量name:

var name = 'Shannon'
var text = `Hello, ${ name }!`
console.log(text)
// <- 'Hello, Shannon!'

模板字符串是支持任何表达式的。使用模板字符串,代码将更容易维护,你无须再手动连接字符串和JavaScript表达式了。
看下面插入日期的例子,是不是又直观又方便:

`The time and date is ${ new Date().toLocaleString() }.`
// <- 'the time and date is 8/26/2015, 3:15:20 PM'

表达式中还可以包含数学运算符:

`The result of 2+3 equals ${ 2 + 3 }`
// <- 'The result of 2+3 equals 5'

鉴于模板字符串本身也是JavaScript表达式,我们在模板字符串中还可以嵌套模板字符串;

`This template literal ${ `is ${ 'nested' }` }!`
// <- 'This template literal is nested!'

模板字符串的另外一个优点是支持多行字符串;

多行文本模板

在ES6之前,如果你想表现多行字符串,你需要使用转义,数组拼合,甚至使用使用注释符做复杂的hacks.如下所示:

var escaped =
'The first line\n\
A second line\n\
Then a third line'var concatenated =
'The first line\n' `
'A second line\n' `
'Then a third line'var joined = [
'The first line',
'A second line',
'Then a third line'
].join('\n')

应用ES6,这种处理就简单多了,模板字符串默认支持多行:

var multiline =
`The first line
A second line
Then a third line`
//在此我向大家推荐一个前端全栈开发交流圈:619586920  突破技术瓶颈,提升思维能力

当你需要返回的字符串基于html和数据生成,使用模板字符串是很简洁高效的,如下所示:

var book = {title: 'Modular ES6',excerpt: 'Here goes some properly sanitized HTML',tags: ['es6', 'template-literals', 'es6-in-depth']
}
var html = `<article><header><h1>${ book.title }</h1></header><section>${ book.excerpt }</section><footer><ul>${book.tags.map(tag => `<li>${ tag }</li>`).join('\n   ')}</ul></footer>
</article>`

上述代码将得到下面这样的结果。空格得以保留,多个li也按我们的预期被合适的渲染:

<article><header><h1>Modular ES6</h1></header><section>Here goes some properly sanitized HTML</section><footer><ul><li>es6</li><li>template-literals</li><li>es6-in-depth</li></ul></footer>
</article>

不过有时候我们并不希望空格被保留,下例中我们在函数中使用包含缩进的模板字符串,我们希望结果没有缩进,但是实际的结果却有四格的缩进。

function getParagraph() {return `Dear Rod,This is a template literal string that's indentedfour spaces. However, you may have expected for itto be not indented at all.Nico`
}

我们可以用下面这个功能函数对生成的字符串进行处理已得到我们想要的结果:

function unindent(text) {return text.split('\n').map(line => line.slice(4)).join('\n').trim()
}

不过,使用被称为标记模板的模板字符串新特性处理这种情况可能会更好。

标记模板

默认情况下,JavaScript会把解析为转义符号,对浏览器来说,以开头的字符一般具有特殊的含义。比如说\n意味着新行,\u00f1表示ñ等等。如果你不想浏览器执行这种特殊解析,你也可以使用String.raw来标记模板。下面的代码就是这样做的,这里我们使用了String.row来处理模板字符串,相应的这里面的\n没有被解析为新行。

var text = String.raw`"\n" is taken literally.
It'll be escaped instead of interpreted.`
console.log(text)
// "\n" is taken literally.
// It'll be escaped instead of interpreted.
//在此我向大家推荐一个前端全栈开发交流圈:619586920  突破技术瓶颈,提升思维能力

我们添加在模板字符串之前的String.raw前缀,这就是标记模板,这样的模板字符串在被渲染前被该标记代表的函数预处理。
一个典型的标记模板字符串如下:

tag`Hello, ${ name }. I am ${ emotion } to meet you!`

实际上,上面标记模板可以用以下函数形式表示:

tag(['Hello, ', '. I am ', ' to meet you!'],'Maurice','thrilled'
)

我们还是用代码来说明这个概念,下述代码中,我们先定义一个名为tag函数:

function tag(parts, ...values) {return parts.reduce((all, part, index) => all + values[index - 1] + part)
}

然后我们调用使用使用标记模板,不过此时的结果和不使用标记模板是一样的,这是因为我们定义的tag函数实际上并未对字符串进行额外的处理。

var name = 'Maurice'
var emotion = 'thrilled'
var text = tag`Hello, ${ name }. I am ${ emotion } to meet you!`
console.log(text)
// <- 'Hello Maurice, I am thrilled to meet you!'

我们看一个进行额外处理的例子,比如转换所有用户输入的值为大写(假设用户只会输入英语),这里我们定义标记函数upper来做这件事:

function upper(parts, ...values) {return parts.reduce((all, part, index) =>all + values[index - 1].toUpperCase() + part)
}
var name = 'Maurice'
var emotion = 'thrilled'
upper`Hello, ${ name }. I am ${ emotion } to meet you!`
// <- 'Hello MAURICE, I am THRILLED to meet you!'

既然可以转换输入为大写,那我们再进一步想想,如果提供合适的标记模板函数,使用标记模板,我们还可以对模板中的表达式进行各种过滤处理,比如有这么一个场景,假设表达式的值都来自用户输入,假设有一个名为sanitize的库可用于去除用户输入中的html标签,那通过使用标记模板,就可以有效的防止XSS攻击了,使用方法如下。

function sanitized(parts, ...values) {return parts.reduce((all, part, index) =>all + sanitize(values[index - 1]) + part)
}
var comment = 'Evil comment<iframe src="http://evil.corp"></iframe>'
var html = sanitized`<div>${ comment }</div>`
console.log(html)
// <- '<div>Evil comment</div>'

ES6中的另外一个大的改变是提供了新的变量声明方式:let和const声明,下面我们一起来学习。

let & const 声明

可能很早之前你就听说过 let 了,它用起来像 var 但是,却有不同的作用域规则。
JavaScript的作用域有一套复杂的规则,变量提升的存在常常让新手忐忑不安。变量提升,意味着无论你在那里声明的变量,在浏览器解析时,实际上都被提升到了当前作用域的顶部被声明。看下面的这个例子:

function isItTwo(value) {if (value === 2) {var two = true}return two
}
isItTwo(2)
// <- true
isItTwo('two')
// <- undefined

尽管two是在代码分支中被声明,之后被外部分支引用,上述的JS代码还是可以工作的。var 声明的变量two实际是在isItTwo顶部被声明的。由于声明提升的存在,上述代码其实和下面代码的效果是一样的

function isItTwo(value) {var twoif (value === 2) {two = true}return two
}

带来了灵活性的同事,变量提升也带来了更大的迷惑性,还好ES6 为我们提供了块作用域。
块作用域和let 声明
相比函数作用域,块作用域允许我们通过if,for,while声明创建新作用域,甚至任意创建{}块也能创建新的作用域:

{{{{{ var deep = 'This is available from outer scope.'; }}}}}
console.log(deep)
// <- 'This is available from outer scope.'

由于这里使用的是var,考虑到变量提升的存在,我们在外部依旧可以读取到深层中的deep变量,这里并不会报错。不过在以下情况下,我们可能希望这里会报错:
访问内部变量会打破我们代码中的某种封装原则;
父块中已有有一个一个同名变量,但是内部也需要用同名变量;
使用let就可以解决这个问题,let 创建的变量在块作用域内有效,在ES6提出let以前,想要创建深层作用域的唯一办法就是再新建一个函数。使用let,你只需添加另外一对{}:

let topmost = {}
{let inner = {}{let innermost = {}}// attempts to access innermost here would throw
}
// attempts to access inner here would throw
// attempts to access innermost here would throw

在for循环中使用let是一个很好的实践,这样定义的变量只会在当前块作用域内生效。

for (let i = 0; i < 2; i++) {console.log(i)// <- 0// <- 1
}
console.log(i)
// <- i is not defined

考虑到let声明的变量在每一次循环的过程中都重复声明,这在处理异步函数时就很有效,不会发生使用var时产生的诡异的结果,我们看一个具体的例子。
我们先看看 var 声明的变量是怎么工作的,下述代码中 i变量 被绑定在 printNumber 函数作用域中,当每个回调函数被调用时,它的值会逐步升到10,但是当每个回调函数运行时(每100us),此时的i的值已经是10了,因此每次打印的结果都是10.

function printNumbers() {for (var i = 0; i < 10; i++) {setTimeout(function () {console.log(i)}, i * 100)}
}
printNumbers()

使用let,则会把i绑定到每一个块作用域中。每一次循环 i 的值还是在增加,但是每次其实都是创建了一个新的 i ,不同的 i 之间不会相互影响 ,因此打印出的就是预想的0到9了。

function printNumbers() {for (let i = 0; i < 10; i++) {setTimeout(function () {console.log(i)}, i * 100)}
}
printNumbers()

为了细致的讲述let的工作原理, 我们还需要弄懂一个名为 Temporal Dead Zone 的概念。
Temporal Dead Zone
简言之,如果你的代码类似下面这样,就会报错。即在某个作用域中,在let声明之前调用了let声明的变量,导致的问题就是由于,Temporal Dead Zone(TDZ)的存在。

{console.log(name)// <- ReferenceError: name is not definedlet name = 'Stephen Hawking'
}

如果定义的是一个函数,函数中引用了name变量则是可以的,但是这个函数并未在声明前执行则不会报错。如果let声明之前就调用了该函数,同样会导致TDZ。

// 不会报错
function readName() {return name
}
let name = 'Stephen Hawking'
console.log(readName())
// <- 'Stephen Hawking'
// 会报错
function readName() {return name
}
console.log(readName())
// ReferenceError: name is not defined
let name = 'Stephen Hawking'

即使像下面这样let定义的变量没有被赋值,下面的代码也会报错,原因依旧是它试图在声明前访问一个被let定义的变量

function readName() {return name
}
console.log(readName())
// ReferenceError: name is not defined
let name

下面的代码则是可行的:

function readName() {return name
}
let name
console.log(readName())
// <- undefined
//在此我向大家推荐一个前端全栈开发交流圈:619586920  突破技术瓶颈,提升思维能力

TDZ的存在使得程序更容易报错,由于声明提升和不好的编码习惯常常会存在这样的问题。在ES6中则可以比较好的避免了这种问题了,需要注意的是let声明的变量同样存在声明提升。这意味着,变量会在我们进入块作用域时就会创建,TDZ也是在这时候创建的,它保证该变量不许被访问,只有在代码运行到let声明所在位置时,这时候TDZ才会消失,访问限制才会取消,变量才可以被访问。

Const 声明

const声明也具有类似let的块作用域,它同样具有TDZ机制。实际上,TDZ机制是因为const才被创建,随后才被应用到let声明中。const需要TDZ的原因是为了防止由于变量提升,在程序解析到const语句之前,对const声明的变量进行了赋值操作,这样是有问题的。
下面的代码表明,const具有和let一致的块作用域:

const pi = 3.1415
{const pi = 6console.log(pi)// <- 6
}
console.log(pi)
// <- 3.1415

下面我们说说const和let的主要区别,首先const声明的变量在声明时必须赋值,否则会报错:

const pi = 3.1415
const e // SyntaxError, missing initializer

除了必须初始化,被const声明的变量不能再被赋予别的值。在严格模式下,试图改变const声明的变量会直接报错,在非严格模式下,改变被静默被忽略。

const people = ['Tesla', 'Musk']
people = []
console.log(people)
// <- ['Tesla', 'Musk']

请注意,const声明的变量并非意味着,其对应的值是不可变的。真正不能变的是对该值的引用,下面我们具体说明这一点。
通过const声明的变量值并非不可改变
使用const只是意味着,变量将始终指向相同的对象或初始的值。这种引用是不可变的。但是值并非不可变。
下面的例子说明,虽然people的指向不可变,但是数组本身是可以被修改的。

const people = ['Tesla', 'Musk']
people.push('Berners-Lee')
console.log(people)
// <- ['Tesla', 'Musk', 'Berners-Lee']

const只是阻止变量引用另外一个值,下例中,尽管我们使用const声明了people,然后把它赋值给了humans,我们还是可以改变humans的指向,因为humans不是由const声明的,其引用可随意改变。people 是由 const 声明的,则不可改变。

const people = ['Tesla', 'Musk']
var humans = people
humans = 'evil'
console.log(humans)
// <- 'evil'

如果我们的目的是让值不可修改,我们需要借助函数的帮助,比如使用Object.freeze:

const frozen = Object.freeze(['Ice', 'Icicle', 'Ice cube']
)
frozen.push('Water')
// Uncaught TypeError: Can't add property 3
// object is not extensible

下面我们详细讨论一下const和let的优点

const和let的优点

新功能并不应该因为是新功能而被使用,ES6语法被使用的前提是它可以显著的提升我们代码的可读写和可维护性。let声明在大多数情况下,可以替换var以避免预期之外的问题。使用let你可以把声明在块的顶部进行而非函数的顶部进行。
有时,我们希望有些变量的引用不可变,这时候使用const就能防止很多问题的发生。下述代码中 在checklist函数外给items变量传递引用时就非常容易出错,它返回的todo API和items有了交互。当items变量被改为指向另外一个列表时,我们的代码就出问题了。todo API 用的还是items之前的值,items本身的指代则已经改变。

var items = ['a', 'b', 'c']
var todo = checklist(items)
todo.check()
console.log(items)
// <- ['b', 'c']
items = ['d', 'e']
todo.check()
console.log(items)
// <- ['d', 'e'], would be ['c'] if items had been constant
function checklist(items) {return {check: () => items.shift()
//在此我向大家推荐一个前端全栈开发交流圈:619586920  突破技术瓶颈,提升思维能力}
}

这类问题很难debug,找到问题原因就会花费你很长一段时间。使用const运行时就会报错,可以帮助你可以避免这种问题。
如果我们默认只使用cosnt和let声明变量,所有的变量都会有一样的作用域规则,这让代码更易理解,由于const造成的影响最小,它还曾被提议作为默认的变量声明。
总的来说,const不允许重新指定值,使用的是块作用域,存在TDZ。let则允许重新指定值,其它方面和const类似,而var声明使用函数作用域,可以重新指定值,可以在未声明前调用,考虑到这些,推荐尽量不要使用var声明了

结语

感谢您的观看,如有不足之处,欢迎批评指正。
#获取资料
本次给大家推荐一个免费的学习群,里面概括移动应用网站开发,css,html,webpack,vue node angular以及面试资源等。
对web开发技术感兴趣的同学,欢迎加入Q群:619586920,不管你是小白还是大牛我都欢迎,还有大牛整理的一套高效率学习路线和教程与您免费分享,同时每天更新视频资料。
最后,祝大家早日学有所成,拿到满意offer,快速升职加薪,走上人生巅峰。

查看全文
如若内容造成侵权/违法违规/事实不符,请联系编程学习网邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!

相关文章

  1. 医院哪里双眼皮好多人

    ...

    2024/5/6 22:37:35
  2. 拉双眼皮去什么医院好么

    ...

    2024/4/25 15:45:36
  3. 西安西京做双眼皮多少钱

    ...

    2024/5/1 14:02:40
  4. 开双眼皮恢复时间表2015

    ...

    2024/5/1 8:50:16
  5. 北京双眼皮效果艺星

    ...

    2024/5/1 8:47:25
  6. 眼睛做了国内专业做双眼皮是哪家

    ...

    2024/5/1 8:53:04
  7. 西安开双眼皮哪里好艺星好评

    ...

    2024/5/1 13:31:02
  8. 贴双眼皮的坏处

    ...

    2024/5/1 6:42:46
  9. 割双眼皮疤痕如何去掉

    ...

    2024/5/1 5:43:58
  10. 开双眼皮医院哪个最好

    ...

    2024/5/1 19:16:51
  11. 夹双眼皮多少钱

    ...

    2024/4/21 7:45:57
  12. 割怎样拉成都双眼皮华西

    ...

    2024/5/1 13:50:13
  13. 做完双眼皮输什么液消炎消肿

    ...

    2024/5/1 12:45:49
  14. 双眼皮医院哪好吧

    ...

    2024/5/1 11:39:19
  15. 双眼皮哪里开的好吧

    ...

    2024/5/1 12:05:43
  16. 杭州做双眼皮u-艺星

    ...

    2024/5/1 18:54:06
  17. 双眼皮整形好评?星

    ...

    2024/5/1 12:35:59
  18. 双眼皮问沈阳协和牛

    ...

    2024/5/1 19:48:42
  19. 沈阳铁西哪家做双眼皮便宜

    ...

    2024/5/1 10:46:32
  20. Cannot read property 'getAttribute' of null

    //data: para, //重新传递参数 data: { city: citycode, startTime: STime, endTime: ETime, Status: Status },//para, 报错位置定位在 myChart ec.init(document.getElementById(container));//main改成container myChart 是个全局变量 改成局部变量 //加个局部变量 va…...

    2024/5/1 6:17:06

最新文章

  1. Study--Oracle-01-单实例部署Oracle11G-R2

    Oracle版本发布介绍 Oracle 19c和12c和11g功能区别_数据库_oracle_支持 一、CentOS 7 环境准备 1、软件准备 操作系统&#xff1a;CentOS 7 数据库版本: Oracle11g R2 2、操作系统环境配置 关闭selinux &#xff0c;编辑 /etc/selinux/config文件&#xff0c;设置SELINU…...

    2024/5/7 7:35:56
  2. 梯度消失和梯度爆炸的一些处理方法

    在这里是记录一下梯度消失或梯度爆炸的一些处理技巧。全当学习总结了如有错误还请留言&#xff0c;在此感激不尽。 权重和梯度的更新公式如下&#xff1a; w w − η ⋅ ∇ w w w - \eta \cdot \nabla w ww−η⋅∇w 个人通俗的理解梯度消失就是网络模型在反向求导的时候出…...

    2024/5/6 9:38:23
  3. python爬取B站视频

    参考&#xff1a;https://cloud.tencent.com/developer/article/1768680 参考的代码有点问题&#xff0c;请求头需要修改&#xff0c;上代码&#xff1a; import requests import re # 正则表达式 import pprint import json from moviepy.editor import AudioFileClip, Vid…...

    2024/5/5 8:45:58
  4. 前端路径问题总结

    1.相对路径 不以/开头 以当前资源的所在路径为出发点去找目标资源 语法: ./表示当前资源的路径 ../表示当前资源的上一层路径 缺点:不同位置,相对路径写法不同2.绝对路径 以固定的路径作为出发点作为目标资源,和当前资源所在路径没关系 语法:以/开头,不同的项目中,固定的路径…...

    2024/5/6 10:30:58
  5. 【外汇早评】美通胀数据走低,美元调整

    原标题:【外汇早评】美通胀数据走低,美元调整昨日美国方面公布了新一期的核心PCE物价指数数据,同比增长1.6%,低于前值和预期值的1.7%,距离美联储的通胀目标2%继续走低,通胀压力较低,且此前美国一季度GDP初值中的消费部分下滑明显,因此市场对美联储后续更可能降息的政策…...

    2024/5/7 5:50:09
  6. 【原油贵金属周评】原油多头拥挤,价格调整

    原标题:【原油贵金属周评】原油多头拥挤,价格调整本周国际劳动节,我们喜迎四天假期,但是整个金融市场确实流动性充沛,大事频发,各个商品波动剧烈。美国方面,在本周四凌晨公布5月份的利率决议和新闻发布会,维持联邦基金利率在2.25%-2.50%不变,符合市场预期。同时美联储…...

    2024/5/4 23:54:56
  7. 【外汇周评】靓丽非农不及疲软通胀影响

    原标题:【外汇周评】靓丽非农不及疲软通胀影响在刚结束的周五,美国方面公布了新一期的非农就业数据,大幅好于前值和预期,新增就业重新回到20万以上。具体数据: 美国4月非农就业人口变动 26.3万人,预期 19万人,前值 19.6万人。 美国4月失业率 3.6%,预期 3.8%,前值 3…...

    2024/5/4 23:54:56
  8. 【原油贵金属早评】库存继续增加,油价收跌

    原标题:【原油贵金属早评】库存继续增加,油价收跌周三清晨公布美国当周API原油库存数据,上周原油库存增加281万桶至4.692亿桶,增幅超过预期的74.4万桶。且有消息人士称,沙特阿美据悉将于6月向亚洲炼油厂额外出售更多原油,印度炼油商预计将每日获得至多20万桶的额外原油供…...

    2024/5/6 9:21:00
  9. 【外汇早评】日本央行会议纪要不改日元强势

    原标题:【外汇早评】日本央行会议纪要不改日元强势近两日日元大幅走强与近期市场风险情绪上升,避险资金回流日元有关,也与前一段时间的美日贸易谈判给日本缓冲期,日本方面对汇率问题也避免继续贬值有关。虽然今日早间日本央行公布的利率会议纪要仍然是支持宽松政策,但这符…...

    2024/5/4 23:54:56
  10. 【原油贵金属早评】欧佩克稳定市场,填补伊朗问题的影响

    原标题:【原油贵金属早评】欧佩克稳定市场,填补伊朗问题的影响近日伊朗局势升温,导致市场担忧影响原油供给,油价试图反弹。此时OPEC表态稳定市场。据消息人士透露,沙特6月石油出口料将低于700万桶/日,沙特已经收到石油消费国提出的6月份扩大出口的“适度要求”,沙特将满…...

    2024/5/4 23:55:05
  11. 【外汇早评】美欲与伊朗重谈协议

    原标题:【外汇早评】美欲与伊朗重谈协议美国对伊朗的制裁遭到伊朗的抗议,昨日伊朗方面提出将部分退出伊核协议。而此行为又遭到欧洲方面对伊朗的谴责和警告,伊朗外长昨日回应称,欧洲国家履行它们的义务,伊核协议就能保证存续。据传闻伊朗的导弹已经对准了以色列和美国的航…...

    2024/5/4 23:54:56
  12. 【原油贵金属早评】波动率飙升,市场情绪动荡

    原标题:【原油贵金属早评】波动率飙升,市场情绪动荡因中美贸易谈判不安情绪影响,金融市场各资产品种出现明显的波动。随着美国与中方开启第十一轮谈判之际,美国按照既定计划向中国2000亿商品征收25%的关税,市场情绪有所平复,已经开始接受这一事实。虽然波动率-恐慌指数VI…...

    2024/5/4 23:55:16
  13. 【原油贵金属周评】伊朗局势升温,黄金多头跃跃欲试

    原标题:【原油贵金属周评】伊朗局势升温,黄金多头跃跃欲试美国和伊朗的局势继续升温,市场风险情绪上升,避险黄金有向上突破阻力的迹象。原油方面稍显平稳,近期美国和OPEC加大供给及市场需求回落的影响,伊朗局势并未推升油价走强。近期中美贸易谈判摩擦再度升级,美国对中…...

    2024/5/4 23:54:56
  14. 【原油贵金属早评】市场情绪继续恶化,黄金上破

    原标题:【原油贵金属早评】市场情绪继续恶化,黄金上破周初中国针对于美国加征关税的进行的反制措施引发市场情绪的大幅波动,人民币汇率出现大幅的贬值动能,金融市场受到非常明显的冲击。尤其是波动率起来之后,对于股市的表现尤其不安。隔夜美国股市出现明显的下行走势,这…...

    2024/5/6 1:40:42
  15. 【外汇早评】美伊僵持,风险情绪继续升温

    原标题:【外汇早评】美伊僵持,风险情绪继续升温昨日沙特两艘油轮再次发生爆炸事件,导致波斯湾局势进一步恶化,市场担忧美伊可能会出现摩擦生火,避险品种获得支撑,黄金和日元大幅走强。美指受中美贸易问题影响而在低位震荡。继5月12日,四艘商船在阿联酋领海附近的阿曼湾、…...

    2024/5/4 23:54:56
  16. 【原油贵金属早评】贸易冲突导致需求低迷,油价弱势

    原标题:【原油贵金属早评】贸易冲突导致需求低迷,油价弱势近日虽然伊朗局势升温,中东地区几起油船被袭击事件影响,但油价并未走高,而是出于调整结构中。由于市场预期局势失控的可能性较低,而中美贸易问题导致的全球经济衰退风险更大,需求会持续低迷,因此油价调整压力较…...

    2024/5/4 23:55:17
  17. 氧生福地 玩美北湖(上)——为时光守候两千年

    原标题:氧生福地 玩美北湖(上)——为时光守候两千年一次说走就走的旅行,只有一张高铁票的距离~ 所以,湖南郴州,我来了~ 从广州南站出发,一个半小时就到达郴州西站了。在动车上,同时改票的南风兄和我居然被分到了一个车厢,所以一路非常愉快地聊了过来。 挺好,最起…...

    2024/5/4 23:55:06
  18. 氧生福地 玩美北湖(中)——永春梯田里的美与鲜

    原标题:氧生福地 玩美北湖(中)——永春梯田里的美与鲜一觉醒来,因为大家太爱“美”照,在柳毅山庄去寻找龙女而错过了早餐时间。近十点,向导坏坏还是带着饥肠辘辘的我们去吃郴州最富有盛名的“鱼头粉”。说这是“十二分推荐”,到郴州必吃的美食之一。 哇塞!那个味美香甜…...

    2024/5/4 23:54:56
  19. 氧生福地 玩美北湖(下)——奔跑吧骚年!

    原标题:氧生福地 玩美北湖(下)——奔跑吧骚年!让我们红尘做伴 活得潇潇洒洒 策马奔腾共享人世繁华 对酒当歌唱出心中喜悦 轰轰烈烈把握青春年华 让我们红尘做伴 活得潇潇洒洒 策马奔腾共享人世繁华 对酒当歌唱出心中喜悦 轰轰烈烈把握青春年华 啊……啊……啊 两…...

    2024/5/4 23:55:06
  20. 扒开伪装医用面膜,翻六倍价格宰客,小姐姐注意了!

    原标题:扒开伪装医用面膜,翻六倍价格宰客,小姐姐注意了!扒开伪装医用面膜,翻六倍价格宰客!当行业里的某一品项火爆了,就会有很多商家蹭热度,装逼忽悠,最近火爆朋友圈的医用面膜,被沾上了污点,到底怎么回事呢? “比普通面膜安全、效果好!痘痘、痘印、敏感肌都能用…...

    2024/5/5 8:13:33
  21. 「发现」铁皮石斛仙草之神奇功效用于医用面膜

    原标题:「发现」铁皮石斛仙草之神奇功效用于医用面膜丽彦妆铁皮石斛医用面膜|石斛多糖无菌修护补水贴19大优势: 1、铁皮石斛:自唐宋以来,一直被列为皇室贡品,铁皮石斛生于海拔1600米的悬崖峭壁之上,繁殖力差,产量极低,所以古代仅供皇室、贵族享用 2、铁皮石斛自古民间…...

    2024/5/4 23:55:16
  22. 丽彦妆\医用面膜\冷敷贴轻奢医学护肤引导者

    原标题:丽彦妆\医用面膜\冷敷贴轻奢医学护肤引导者【公司简介】 广州华彬企业隶属香港华彬集团有限公司,专注美业21年,其旗下品牌: 「圣茵美」私密荷尔蒙抗衰,产后修复 「圣仪轩」私密荷尔蒙抗衰,产后修复 「花茵莳」私密荷尔蒙抗衰,产后修复 「丽彦妆」专注医学护…...

    2024/5/4 23:54:58
  23. 广州械字号面膜生产厂家OEM/ODM4项须知!

    原标题:广州械字号面膜生产厂家OEM/ODM4项须知!广州械字号面膜生产厂家OEM/ODM流程及注意事项解读: 械字号医用面膜,其实在我国并没有严格的定义,通常我们说的医美面膜指的应该是一种「医用敷料」,也就是说,医用面膜其实算作「医疗器械」的一种,又称「医用冷敷贴」。 …...

    2024/5/6 21:42:42
  24. 械字号医用眼膜缓解用眼过度到底有无作用?

    原标题:械字号医用眼膜缓解用眼过度到底有无作用?医用眼膜/械字号眼膜/医用冷敷眼贴 凝胶层为亲水高分子材料,含70%以上的水分。体表皮肤温度传导到本产品的凝胶层,热量被凝胶内水分子吸收,通过水分的蒸发带走大量的热量,可迅速地降低体表皮肤局部温度,减轻局部皮肤的灼…...

    2024/5/4 23:54:56
  25. 配置失败还原请勿关闭计算机,电脑开机屏幕上面显示,配置失败还原更改 请勿关闭计算机 开不了机 这个问题怎么办...

    解析如下&#xff1a;1、长按电脑电源键直至关机&#xff0c;然后再按一次电源健重启电脑&#xff0c;按F8健进入安全模式2、安全模式下进入Windows系统桌面后&#xff0c;按住“winR”打开运行窗口&#xff0c;输入“services.msc”打开服务设置3、在服务界面&#xff0c;选中…...

    2022/11/19 21:17:18
  26. 错误使用 reshape要执行 RESHAPE,请勿更改元素数目。

    %读入6幅图像&#xff08;每一幅图像的大小是564*564&#xff09; f1 imread(WashingtonDC_Band1_564.tif); subplot(3,2,1),imshow(f1); f2 imread(WashingtonDC_Band2_564.tif); subplot(3,2,2),imshow(f2); f3 imread(WashingtonDC_Band3_564.tif); subplot(3,2,3),imsho…...

    2022/11/19 21:17:16
  27. 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机...

    win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”问题的解决方法在win7系统关机时如果有升级系统的或者其他需要会直接进入一个 等待界面&#xff0c;在等待界面中我们需要等待操作结束才能关机&#xff0c;虽然这比较麻烦&#xff0c;但是对系统进行配置和升级…...

    2022/11/19 21:17:15
  28. 台式电脑显示配置100%请勿关闭计算机,“准备配置windows 请勿关闭计算机”的解决方法...

    有不少用户在重装Win7系统或更新系统后会遇到“准备配置windows&#xff0c;请勿关闭计算机”的提示&#xff0c;要过很久才能进入系统&#xff0c;有的用户甚至几个小时也无法进入&#xff0c;下面就教大家这个问题的解决方法。第一种方法&#xff1a;我们首先在左下角的“开始…...

    2022/11/19 21:17:14
  29. win7 正在配置 请勿关闭计算机,怎么办Win7开机显示正在配置Windows Update请勿关机...

    置信有很多用户都跟小编一样遇到过这样的问题&#xff0c;电脑时发现开机屏幕显现“正在配置Windows Update&#xff0c;请勿关机”(如下图所示)&#xff0c;而且还需求等大约5分钟才干进入系统。这是怎样回事呢&#xff1f;一切都是正常操作的&#xff0c;为什么开时机呈现“正…...

    2022/11/19 21:17:13
  30. 准备配置windows 请勿关闭计算机 蓝屏,Win7开机总是出现提示“配置Windows请勿关机”...

    Win7系统开机启动时总是出现“配置Windows请勿关机”的提示&#xff0c;没过几秒后电脑自动重启&#xff0c;每次开机都这样无法进入系统&#xff0c;此时碰到这种现象的用户就可以使用以下5种方法解决问题。方法一&#xff1a;开机按下F8&#xff0c;在出现的Windows高级启动选…...

    2022/11/19 21:17:12
  31. 准备windows请勿关闭计算机要多久,windows10系统提示正在准备windows请勿关闭计算机怎么办...

    有不少windows10系统用户反映说碰到这样一个情况&#xff0c;就是电脑提示正在准备windows请勿关闭计算机&#xff0c;碰到这样的问题该怎么解决呢&#xff0c;现在小编就给大家分享一下windows10系统提示正在准备windows请勿关闭计算机的具体第一种方法&#xff1a;1、2、依次…...

    2022/11/19 21:17:11
  32. 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”的解决方法...

    今天和大家分享一下win7系统重装了Win7旗舰版系统后&#xff0c;每次关机的时候桌面上都会显示一个“配置Windows Update的界面&#xff0c;提示请勿关闭计算机”&#xff0c;每次停留好几分钟才能正常关机&#xff0c;导致什么情况引起的呢&#xff1f;出现配置Windows Update…...

    2022/11/19 21:17:10
  33. 电脑桌面一直是清理请关闭计算机,windows7一直卡在清理 请勿关闭计算机-win7清理请勿关机,win7配置更新35%不动...

    只能是等着&#xff0c;别无他法。说是卡着如果你看硬盘灯应该在读写。如果从 Win 10 无法正常回滚&#xff0c;只能是考虑备份数据后重装系统了。解决来方案一&#xff1a;管理员运行cmd&#xff1a;net stop WuAuServcd %windir%ren SoftwareDistribution SDoldnet start WuA…...

    2022/11/19 21:17:09
  34. 计算机配置更新不起,电脑提示“配置Windows Update请勿关闭计算机”怎么办?

    原标题&#xff1a;电脑提示“配置Windows Update请勿关闭计算机”怎么办&#xff1f;win7系统中在开机与关闭的时候总是显示“配置windows update请勿关闭计算机”相信有不少朋友都曾遇到过一次两次还能忍但经常遇到就叫人感到心烦了遇到这种问题怎么办呢&#xff1f;一般的方…...

    2022/11/19 21:17:08
  35. 计算机正在配置无法关机,关机提示 windows7 正在配置windows 请勿关闭计算机 ,然后等了一晚上也没有关掉。现在电脑无法正常关机...

    关机提示 windows7 正在配置windows 请勿关闭计算机 &#xff0c;然后等了一晚上也没有关掉。现在电脑无法正常关机以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容&#xff0c;让我们赶快一起来看一下吧&#xff01;关机提示 windows7 正在配…...

    2022/11/19 21:17:05
  36. 钉钉提示请勿通过开发者调试模式_钉钉请勿通过开发者调试模式是真的吗好不好用...

    钉钉请勿通过开发者调试模式是真的吗好不好用 更新时间:2020-04-20 22:24:19 浏览次数:729次 区域: 南阳 > 卧龙 列举网提醒您:为保障您的权益,请不要提前支付任何费用! 虚拟位置外设器!!轨迹模拟&虚拟位置外设神器 专业用于:钉钉,外勤365,红圈通,企业微信和…...

    2022/11/19 21:17:05
  37. 配置失败还原请勿关闭计算机怎么办,win7系统出现“配置windows update失败 还原更改 请勿关闭计算机”,长时间没反应,无法进入系统的解决方案...

    前几天班里有位学生电脑(windows 7系统)出问题了&#xff0c;具体表现是开机时一直停留在“配置windows update失败 还原更改 请勿关闭计算机”这个界面&#xff0c;长时间没反应&#xff0c;无法进入系统。这个问题原来帮其他同学也解决过&#xff0c;网上搜了不少资料&#x…...

    2022/11/19 21:17:04
  38. 一个电脑无法关闭计算机你应该怎么办,电脑显示“清理请勿关闭计算机”怎么办?...

    本文为你提供了3个有效解决电脑显示“清理请勿关闭计算机”问题的方法&#xff0c;并在最后教给你1种保护系统安全的好方法&#xff0c;一起来看看&#xff01;电脑出现“清理请勿关闭计算机”在Windows 7(SP1)和Windows Server 2008 R2 SP1中&#xff0c;添加了1个新功能在“磁…...

    2022/11/19 21:17:03
  39. 请勿关闭计算机还原更改要多久,电脑显示:配置windows更新失败,正在还原更改,请勿关闭计算机怎么办...

    许多用户在长期不使用电脑的时候&#xff0c;开启电脑发现电脑显示&#xff1a;配置windows更新失败&#xff0c;正在还原更改&#xff0c;请勿关闭计算机。。.这要怎么办呢&#xff1f;下面小编就带着大家一起看看吧&#xff01;如果能够正常进入系统&#xff0c;建议您暂时移…...

    2022/11/19 21:17:02
  40. 还原更改请勿关闭计算机 要多久,配置windows update失败 还原更改 请勿关闭计算机,电脑开机后一直显示以...

    配置windows update失败 还原更改 请勿关闭计算机&#xff0c;电脑开机后一直显示以以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容&#xff0c;让我们赶快一起来看一下吧&#xff01;配置windows update失败 还原更改 请勿关闭计算机&#x…...

    2022/11/19 21:17:01
  41. 电脑配置中请勿关闭计算机怎么办,准备配置windows请勿关闭计算机一直显示怎么办【图解】...

    不知道大家有没有遇到过这样的一个问题&#xff0c;就是我们的win7系统在关机的时候&#xff0c;总是喜欢显示“准备配置windows&#xff0c;请勿关机”这样的一个页面&#xff0c;没有什么大碍&#xff0c;但是如果一直等着的话就要两个小时甚至更久都关不了机&#xff0c;非常…...

    2022/11/19 21:17:00
  42. 正在准备配置请勿关闭计算机,正在准备配置windows请勿关闭计算机时间长了解决教程...

    当电脑出现正在准备配置windows请勿关闭计算机时&#xff0c;一般是您正对windows进行升级&#xff0c;但是这个要是长时间没有反应&#xff0c;我们不能再傻等下去了。可能是电脑出了别的问题了&#xff0c;来看看教程的说法。正在准备配置windows请勿关闭计算机时间长了方法一…...

    2022/11/19 21:16:59
  43. 配置失败还原请勿关闭计算机,配置Windows Update失败,还原更改请勿关闭计算机...

    我们使用电脑的过程中有时会遇到这种情况&#xff0c;当我们打开电脑之后&#xff0c;发现一直停留在一个界面&#xff1a;“配置Windows Update失败&#xff0c;还原更改请勿关闭计算机”&#xff0c;等了许久还是无法进入系统。如果我们遇到此类问题应该如何解决呢&#xff0…...

    2022/11/19 21:16:58
  44. 如何在iPhone上关闭“请勿打扰”

    Apple’s “Do Not Disturb While Driving” is a potentially lifesaving iPhone feature, but it doesn’t always turn on automatically at the appropriate time. For example, you might be a passenger in a moving car, but your iPhone may think you’re the one dri…...

    2022/11/19 21:16:57