《韩顺平JavaScript》视频+阮一峰《ECMAScript 6》学习笔记

来源:互联网 发布:指南针文献数据库 编辑:程序博客网 时间:2024/06/05 03:16

标准的JavaScript应该包括

核心(ECMAScript)、文档对象模型(DOM)、浏览器对象模型(BOM

外联JavaScript文件:

<script type = ”文件路径”s r c = ” j s文件名”/ >XHML语法)

< script type = ”文件路径”s r c = ” j s文件名”></script>

带有src属性的<script>标签在<></>之间不允许再出现另外的js代码

js是弱数据类型语言(又称为松散类型),其变量类型由js引擎决定


《基础类型以及基本运算》

运算符+-*/%取模

逻辑运算符,逻辑运算同样由短路,0、“”、falsenullundefinedNaN均表示false

window .prompt( )相当于python中的

三大流程控制语句:选择、分支、循环

j s中有一个arguments,在函数中可以访问所有传入值(即形参)

js的同一数组中的元素可以是任意类型,对于数组下标访问越界的情况,也和java类似,会返回undefined,但是如果直接对越界的下标进行赋值则是允许的,即js的数组是可以动态增长的(因为js是解释型语言),js同样有java中的foreach语法

数组名.split(分割标准);

数组名.length();

j s的函数传值与java相同,属于传址类型



同样地,在js中仍然是Everything is object.

java一样同样具有instanceof运算

function 类名/原型对象名( ) {

this . variable_name1=values;//公有数据

this . variable_name2=values;//公有数据

,,,

var variable_name3=values;//私有数据

var variable_name4=values;//私有数据

this . function_name1=function ( ) { }//公有方法(特权方法,可以访问私有变量)

var function_name2=function ( ) { }//私有方法

}

1.工厂方法

2.使用构造函数来定义类(原型对象)

3.使用prototype

4.构造函数以及原型混合方式

5.动态原型方式


js是基于对象的,初衷并不是面向对象,而且也没有类,只有原型对象,但“原型对象”在C#Java中也就是“类”,所以后来干脆说js是 支持面向对象的。

给对象添加方法的两种方式:

1)

function类名(){

this.属性;

}


var对象名=new类名();

function函数名(){

语句;

}

对象名.属性名=函数名//这样就相当于把函数赋给对象名.属性名,此时这个属性名就表示一个函数

(2)

对象名.属性名=function(参数列表){

//语句。。。

}

调用:

对象名.属性名(实际参数)

js中调用函数并不根据参数的匹配,而只是根据函数名

但是,以上增加函数的方法都是每个对象有自己独立一份的函数(即每个对象的函数都占一份独立的空间)。那么怎么给类自己增加方法(就像C++,Java中那样)呢?

即:

function class_name ( ) {

class_name.prototype.function_name(){

//function_expression...;

}

}


Java相同的是,js也有Object类,它同样是所有类的基类

Object的一些属性:

constructor-对象的构造函数

prototype-获得累的prototype对象,static性质

主要方法;

hasOwnPropertyproperty-是否属于本类定义的属性

isPropertyOfobject-是否是指定类的prototype

toString()-返回对象对应的字符串

value Of()-返回对象对应的原始类型值



《继承》

js可以通过对象冒充实现多重继承的效果,但是用的比较少



《重载》

js默认不支持重载,但是由于其arguments关键字(以实现与Java中可变参数列表同等功能)的存在,也可以认为js是天然存在重载功能的语言

《重写》

子类可以重写父类方法以达到覆盖


有望加入ES7的功能:

Stage 0:

Function Bind Syntax:函数的绑定运算符

String.prototype.at:字符串的静态方法at

Stage 1:

Class and Property Decorators:Class的修饰器

Class Property Declarations:Class的属性声明

Additional export-from Statements:export的写法改进

String.prototype.{trimLeft,trimRight}:字符串删除头尾空格的方法

Stage 2:

Rest/Spread Properties:对象的Rest参数和扩展运算符

Stage 3

SIMD API:“单指令,多数据”命令集

Async Functions:async函数

Object.values/Object.entries:Object的静态方法values()entries()

String padding:字符串长度补全

Trailing commas in function parameter lists and calls:函数参数的尾逗号

Object.getOwnPropertyDescriptors:Object的静态方法

getOwnPropertyDescriptors

Stage 4:

Array.prototype.includes:数组实例的includes方法

Exponentiation Operator:指数运算符



《变量提升》


ES6新增了let命令,用来声明变量。它的用法类似于var ,但是

@@@所声明的变量,只在let命令所在的代码块内有效,即let不存在变量提升,此种语法很适合定义for循环中的控制变量。

@@@显然,let不允许在相同作用域内重复声明同一个变量。

@@@正因为不存在变量提升,所以该类变量一定要在声明之后使用。

函数声明和变量声明总是会被解释器悄悄地被“提升”到方法体的最顶部。

变量赋值并没有被提升,只是声明被提升了。但是,函数的声明有点不一样,函数体也会一同被提升。但是请注意,函数的声明有两种方式:

    function test(){

      foo();//TypeError"foo is not afunction"

      bar(); // "this will run!"

        var foo = function ( ) { //变量指向函数表达式

        alert("this won't run!");

        }

        function bar() { //函数声明函数名为bar

        alert("this will run!");

        }

}

test();

这个例子里面,只有函数式的声明才会连同函数体一起被提升。foo的声明会被提升,但是它指向的函数体只会在执行的时候才被赋值。

上面的东西涵盖了提升的一些基本知识,它们看起来也没有那么迷惑。但是,在一些特殊场景,还是有一定的复杂度的。


《暂时性死区》(temporaldead zone,简称TDZ)


ES6明确规定,如果区块中存在letconst命令,这个区块对这些命令声明的变量,从一开始就形成了封闭作用域。凡是在声明之前就使用这些变量,就会报错。

总之,在代码块内,使用let命令声明变量之前,该变量都是不可用的。这在语法上,称为“暂时性死区“。

if (true) {

// TDZ开始

tmp = 'abc'; // ReferenceError

console.log(tmp); // ReferenceError

let tmp; // TDZ结束

console.log(tmp); // undefined

tmp = 123;

cosole.log(tmp);

}

@@@同时,正因为有TDzone的存在是的typeof这种操作不再总是safe。(继续从前的用法可能会跑出ReferenceError异常)

@@@但是,当typeofTDZ没有冲突的时候,若typeof一个未定义的变量不会报错而是正常返回‘undefined’

@@@ES6规定暂时性死区和修订变量提升,主要是为了减少运行时错误,防止在变量声明前就使用这个变量,从而导致意料之外的行为。这样的错误在ES5是很常见的,现在有了这种规定,避免此类错误就很容易了。



《块级作用域》

es5var定义变量带来了许多问题,比如内层嵌套中的for循环控制变量若用var定义,则可能泄露为全局变量。

那么,从另一个角度来看,let关键字给ECMAScript6带来了块级作用域


《在块级作用域中声明函数》

es5不允许在块级作用域中声明函数

es6明确规定可以再块级作用域中声明函数,并且,在块级作用域中,函数声明类似于let,在块级作用域之外不可引用。



const变量必须在声明时即初始化,声明后只读不得更改。const声明变量不存在变量提升,但同样存在暂时性死区。

@@@对于复合类型的变量,变量名不指向数据,而是指向数据所在的地址。const命令只是保证变量名指向的地址不变,并不保证该地址的数据不变,所以将一个对象声明为常量必须非常小心。

@@@在上面的条件下,如果真的想将对象冻结,应该使用Object . freeze方法。


ES6为了改变这一点,一方面规定,为了保持兼容性,var命令和 function命令声明的全局变量,依旧是全局对象的属性;另一方面规定,let命令、const命令、class命令声明的全局变量,不属于全局对象的属性。也就是说,ES6开始,全局变量将逐步与全局对象的属性脱钩。


《变量的解构赋值》

var [a, b, c] = [1, 2, 3];

@@@可以从数组中提取值,按照对应位置,对变量赋值。

@@@本质上,这种写法属于“模式匹配”,只要等号两边的模式相同,左边的变量就会被赋予对应的值。下面是一些使用嵌套数组进行解构的例子。如果解构不成功,变量的值就等于 undefined

另一种情况是不完全解构,即等号左边的模式,只匹配一部分的等号右边的数组。这种情况下,解构虽然不完全,但是依然可以成功。

@@@模式匹配结果:

1

let [head, ...tail] = [1, 2, 3, 4];

head // 1

tail // [2, 3, 4]

2

let [x, y, ...z] = ['a'];

x // "a"

y // undefined

z // []


@@@解构赋值不仅适用于var命令,也适用于letconst命令。对于Set结构,也可以使用数组的解构赋值。

@@@事实上,只要某种数据结构具有Iterator(迭代器,这里的意思是某种数据属于迭代器类型)接口,都可以采用数组形式的解构赋值。

@@@解构赋值允许指定默认值。ES6内部使用严格相等运算符(===),判断一个位置是否有值。所以,如果一个数组成员不严格等于undefined,默认值是不会生效的。如果一个数组成员是null,默认值就不会生效,因为null不严格等于undefined

@@@对象的解构与数组有一个重要的不同。数组的元素是按次序排列的,变量的取值由它的位置决定;而对象的属性没有次序,变量必须与属性同名,才能取到正确的值。也就是说,对象的解构赋值的内部机制,是先找到同名属性,然后再赋给对应的变量。真正被赋值的是后者,而不是前者。





基础类型以及基本运算(es5

变量提升

暂时性死区

块级作用域

允许在块级作用域中声明函数

变量的解构赋值

0 0
原创粉丝点击