常量
支持常量(也被称为“不可变的变量”),该变量不能重新分配新内容。注意:仅仅是使变量自身不可变,而不是它所被分配的内容(例如,如果该内容是一个对象,这个内容对象仍然可变)。
//ES6
const PI = 3.141593
PI > 3.0 //true
//ES5
//通过定义对象属性的方式来定义不变的变量
Object.defineProperty(typeof global === "object" ? global : window, "PI", {
value: 3.141593,
enumerable: true,
writable: false,
configurable: false
})
PI > 3.0;
作用域
- 块作用域变量
块作用域变量和常量不存在变量提升
//变量提升要点解析
//tip1: 变量提升是把变量提到当前函数作用域的顶部, 变量提升只是提升变量的声明,并不会提升赋值
//例1:
console.log(name); //报错 name is not defined
//例2
console.log(name); //undefined name在运行时首先被提升到函数顶部, name此时是被定义过的,但是并没有提升赋值, 所以是undefined
var name = 'es6';
//例3
var name = 'es6';
function myFunc(){ //函数有自己的作用域
console.log(name); //undefined 该函数作用域内的变量name提升至当前函数顶部
var name = 'es5';
console.log(name);//es5
}
myFunc();
console.log(name); //es6
// 建议: 把变量声明放在作用域开始位置(顶端),以防止意外 //
//tip2: 函数也可被提升, 但是需要注意两种方式的区别:1.函数声明式方式提升 2.函数表达式方式提升
//例4:函数声明式提升
myFunc(); //打印 es6 myFunc函数被提升至作用域顶部,可以被执行
function myFunc(){
console.log('es6');
}
//例五: 函数表达式方式提升
myFunc(); //报错:myFunc is not a function 解释:此时变量myFunc被提升至顶部,但是,正如上面所述,变量的赋值并不会被提升,此时的myFunc是undefined
var myFunc = function(){
console.log('es6');
}
let 变量声明, 可支持块块作用域
//例1 let 可声明块作用域变量
//ES6
var a = [1,2,3];
for (let i = 0; i < a.length; i++) {
//i x 只在当前块作用域内有效
let x = a[i]
…
}
console.log(i); //i is not defined
console.log(x); //x is not defined
//ES5
var a = [1,2,3];
for (var i = 0; i < a.length; i++) {
var x = a[i]
…
}
console.log(i); //3
console.log(x); //3
例2:
//ES6
let callbacks = []
for (let i = 0; i <= 2; i++) {
callbacks[i] = function () { return i * 2 }
}
callbacks[0]() === 0
callbacks[1]() === 2
callbacks[2]() === 4
//ES5
var callbacks = [];
for (var i = 0; i <= 2; i++) {
(function (i) {
callbacks[i] = function() { return i * 2; };
})(i);
}
callbacks[0]() === 0;
callbacks[1]() === 2;
callbacks[2]() === 4;
- 块作用域函数
//我们来看一个构造独立作用域,防止全局污染的例子
//ES6 只需{}
{
function foo () { return 1 }
foo() === 1
{
function foo () { return 2 }
foo() === 2
}
foo() === 1
}
//ES5 需要被包裹在一个立即执行方法里
(function () {
var foo = function () { return 1; }
foo() === 1;
(function () {
var foo = function () { return 2; }
foo() === 2;
})();
foo() === 1;
})();
箭头函数
//更优美的闭包语法
/对比1 ::: 更方便的return /////
//ES6
odds = evens.map(v => v + 1)
pairs = evens.map(v => ({ even: v, odd: v + 1 }))
nums = evens.map((v, i) => v + i)
//ES5
odds = evens.map(function (v) { return v + 1; });
pairs = evens.map(function (v) { return { even: v, odd: v + 1 }; });
nums = evens.map(function (v, i) { return v + i; });
//对比2 ::: {}函数体 /
//es6
nums.forEach(v => { //函数体
if (v % 5 === 0)
fives.push(v)
})
//es5
nums.forEach(function (v) {//函数体
if (v % 5 === 0)
fives.push(v);
});
//对比3 :: 聪明的This指向---更简便的处理当前对象上下文//
//ES6
this.nums.forEach((v) => {
if (v % 5 === 0)
this.fives.push(v); //this与nums同作用域(或者说this指向nums对象的上下文)
})
//ES5
// 变体 1
var self = this; //保存当前实例对象
this.nums.forEach(function (v) {
if (v % 5 === 0)
self.fives.push(v);
});
// 变体 2 ( 仅ECMAScript 5.1支持)
this.nums.forEach(function (v) {
if (v % 5 === 0)
this.fives.push(v);
}.bind(this)); //通过bind方法绑定实例对象,注意: bind()返回一个函数,并未执行. (与call、apply不同)
///
//tips: this测试笔记 对比nodejs 和 浏览器
///
///测试1
console.log(this);// node: 空对象{}(nodejs的该对象用于文件之间的访问, 该this其实就是exports对象,而exports对象是module.exports的引用,require返回的始终是module.exports 关于exports的只是请查看 [module](http://cnodejs.org/topic/5231a630101e574521e45ef8)) browser: Window对象
function test(){
console.log(this);
//打印结果 nodejs:node的global对象 browser:Window对象
ab();
function ab(){
console.log(this);
//打印结果 nodejs: node的global对象 browser:Window对象
}
}
test();
///测试2
//实例化后的函数 this指向该实例对象 (同浏览器结果)
function animal(){
console.log(this);
}
var dog = new animal(); //打印: animal {}
待续…