es6-js

暂时性死区
Javascript在es6中提出了暂时性死区,其本质是:

只要一进入当前作用域,用let声明的变量实际上就已经存在了,但是需要等到let声明变量之后才能使用,相比较es5,使用var声明的变量会存在变量提升的问题,即使用var声明的变量在声明之前也是可以使用的,其值为undefined。不存在变量提升的情况下,这样做是会直接报错的。
es6中的块级作用域

考虑到环境导致的行为差异太大,应该避免在块级作用域内声明函数。如果确实需要,也应该写成函数表达式,而不是函数声明语句。

函数声明
{
let a = ‘abc’;
function f (){
return a;
}
}
函数表达式:
{
let a =’and’;
let f = function(){
return a;
}
}

do表达式

本质上,块级作用域是一个语句,将多个操作封装在一起,没有返回值:
{
let t = f();
t = t * t +1
}

在块级作用域之外,没有办法得到t的值,因为块级作用域不返回值,除非t是全局变量现在有一个提案,是得块级作用域变为表达式,办法就是在块级作用域前加上do,变为do表达式:

let x = do{
let t = f ();
t = t +1
}

上面的代码中x会得到整个块级作用域的返回值。

const命令

const声明一个只读常量,和java相似,常量不能被改变。

const的作用域和let相同,只在块级作用域内有效

if(true){
const MAX = 5;
}
MAX
这样做会报错

const本质:const实际上保证的不是变量的值不能改动,而是变量指向的内存地址不得改动,对于简单数据类型,值就保存在变。量指向的那个内存地址,等同于常量。但是对于复合类型的数据(对象和数组),变量指向的是内存地址,保存的是指针,const只能保证指针是固定的,但是其指向的数据结构是可变的。

const foo = {}
//可以改变数据结构
foo.prop =123;
foo.prop //123
//不可以改变指针指向的地址
foo = {} //会报错 foo is read-only

如果想要使对象不可变,应该使用Object.freeze方法:
const foo = Object.freeze({});
foo.prop = 123 //严格模式下会报错,一般迷失下不会起作用

(在java中可以通过将对象中的属性声明为private使外界不能修改Java对象)

顶层对象的属性

顶层对象,在浏览器中指的是window对象,在node中指的是global对象。
顶层对象的属性和全局变量挂钩,被认为是js最大的设计败笔。这样的设计会导致几个很大的问题,首先是没法在编译的时候就报出变量未声明的错误,因为全局变量可能是顶层对象的属性创建的,而属性的创造是在程序在运行时动态生成的,这样会导致,代码没有跑到的地方,错误就发现不了(对比java的静态检查,简直太人性化了),刚好顶层对象的属性又是可以到处读写的,这样非常不利于模块化编程,因为模块化的基本要求就是要相对独立,所以如果用js写大型项目将会变得很危险,可能给变量取个合适的名字都会成为一个问题。

es6为了改变这一点作恶了什么事情呢?

var 和function声明的全局变量依然是顶层对象的属性(为了兼容性),let const class命令声明的全局变量不属于顶层对象,可以看到js在慢慢的变好。

global对象

js之所以号称坑最多的语言,不是没有道理的,因为在es5中顶层对象的各种实现里面是不统一的。

-在浏览器中,顶层对象是window,在node和web worker中没有window
-浏览器和webworker中,self指向顶层对象,但是node没有self(self不是python中的保留字么,js什么时候用到了这个玩意,)

-node中的顶层对象是global

同一段变量为了能够在各种环境中都能取到顶层对象,使用this变量会好一点,这个是统一的,但是也有局限性。

-全局环境中,this会返回顶层对象,但是node和es6模块中,this返回的是当前模块。(没毛病,这样做是合理地)

-函数里面的this,如果函数不是作为对象的方法运行,而是单纯的作为函数运行,this指向顶层对象,但是在严格模式下this会返回undefined‘

-不管是严格模式还是普通模式,new function(){return this},总司会返回全局对象,但是如果浏览器使用了安全政策CSP(Content Security Policy),那么eval,new function 都可能无法使用。eval(string)该函数接收一个原始字符串,并计算字符串的值,字符串应该包含js表达式。

下面是两个在任何环境中都能够取到顶层对象的方法: // 方法一 (typeof window !== ‘undefined’ ? window
(typeof process === ‘object’ &&
typeof require === ‘function’ &&
typeof global === ‘object’)
? global
: this);

// 方法二
var getGlobal = function () {
if (typeof self !== ‘undefined’) { return self; }
if (typeof window !== ‘undefined’) { return window; }
if (typeof global !== ‘undefined’) { return global; }
throw new Error(‘unable to locate global object’);
};
es6变量的解构赋值

es6支持模式匹配(python也支持,Java不支持这种赋值的方式),用法:
let [a,b,c] = [1,2,3]
//a = 1
只要等号的两边模式相同,就能够按照既定的规则进行赋值,如果解构失败,相应位置上的值就是undefined。
let [foo] = [];
let [bar, foo] = [1];
foo的值都是undefined,而bar的值是1
不完全解构:
let [x, y] = [1, 2, 3];
x // 1
y // 2

let [a, [b], d] = [1, [2, 3], 4];
a // 1
b // 2
d // 4
在什么情况下解构会失败?

当等号右边的值是一个不可迭代对象(没有iterator接口),那么解构会失败。
事实上,只要某种数据解构只要具有iterator接口,都可以采用数组形式的解构赋值:
function* fibs(){
let a = 0;
let b =1;
while(true){
yield a; //函数会返回此时的a,但是操作数栈依然存在
[a,b] = [b,a+b];
}
}
let[frist,second,third,fourth,fifth,sixth] =fibs();
six //5

呵呵,这特么不就是python里面的生成器么,fibs()函数就是斐波那契数列。什么是斐波那契数列?斐波那契数列指的是数列的下一个值始终等于前面两个值的和。在java中要生成斐波那契数列稍微麻烦一点,因为一旦函数返回值,就出栈了。但是要实现打印斐波那契数列还是不难,那么如果要用Java实现一个斐波那契数列应该怎么办呢?

思路:斐波那契数列的数学表达式可以抽象为[fn,f(n-1)+f(n),f(n-1)+fn+f(n+1)]
import java.util.ArrayList;

public class Main {

public static void main(String[] args) {
    System.out.println(createFibArr(10));
}

private static ArrayList createFibArr(int n){
    ArrayList fibs = new ArrayList();
    Integer num = 0;
    for (int i=1;i<=n;i++){
        num = getFibNum(i);
        fibs.add(num);
    }
    return fibs;
}

private static int getFibNum(int n){

    if(n <= 2){
        return 1;
    }else{
        return getFibNum(n-1) + getFibNum(n-2);
    }
}

}

你可能感兴趣的:(js)