1、let
A:let关键字:将变量绑定到所在的任意作用域
function process(){
//do something
} //在这个块中定义的内容完事就可以销毁
{
let someReallyBigData = {…………}; process(someReallyBigData);
} vra btn = document.getElementById("my_button");
btn.addEventListener('click',function click(evt){
console.info("click");
})
B:let循环
for(let i = 0 ; i < 10 ; i++){ console.info(i); }
注意:let不仅将i绑定到for循环中,事实上将其绑定到了循环中的每一个迭代中,确保上一个循环迭代结束的时候对它的值重新进行赋值
C:可以解决闭包中的作用域问题
for(var i = 1 ; i <= 5 ; i++){
(function(j){
setTimeout(function timer(){
console.info(j)
},j * 1000);
})(i);
} 作用相同 for(var i = 1 ; i <= 5 ; i++){
let j = i ;
setTimeout(function timer(){
console.info(j)
},j * 1000);
}
2、const
创建块作用域变量,但其值是固定的(常量),之后任何试图修改值得操做都会引起错误
3、编译器---函数声明与函数表达式
函数声明:
foo(); //success
function foo(){
console.info(a); //undefined
var a = 2;
}
解释为
function foo(){
var a;
console.info(a); //undefined
a = 2;
}
foo();
函数表达式:
foo(); //TypeError
bar(); //ReferenceError
var foo = function bar(){
//....
}
4、模块机制---ES6
bar.js
function hello(who){
return "Let me introduce:" + who;
}
export hello; foo.js
//仅从“bar”模块中导入hello()
import hello from "bar"; var hungry = "hippo";
function awesome(){
console.info(hello(hungry).toUpperCase());
}
export awesome; baz.js
//导入完整的“foo”与“bar”模块
module foo from "foo";
module bar from "bar";
console.info(bar.hello("rhino")); //Let me introduce:rhino
foo.awesome(); //LET ME INTRODUCE:HIPPO
5、ES6箭头函数 -- 当做function关键字的简写以及解决关于this绑定问题
箭头函数就是function关键字的简写,用于函数声明,放弃了所有普通的this绑定原则,取而代之的是用当前的语法作用域覆盖了this本来的值,具体参考以下例子:
var obj = {
id : "awesome",
cool : function coolFn(){
console.info(this.id);
}
} var id = "not awesome"; obj.cool(); //awesome
//cool函数丢失了同this之间的绑定
setTimeout(obj.cool,100); //not awesome //可以通过var self = this;解决
var obj = {
count : 0,
cool : function coolFn(){
var self = this; if (self.count < 1) {
setTimeout(function timer(){
self.count++;
console.info("awesome?");
},100)
};
}
}
obj.cool(); //awesome? //这样一来代码过于冗长,通过ES6的箭头函数
var obj = {
count : 0,
cool : function coolFn(){
if (this.count < 1) {
setTimeout( () => {
this.count++;
console.info("awesome?");
},100)
};
}
}
obj.cool(); //awesome? //还可以通过bind()绑定
var obj = {
count : 0,
cool : function coolFn(){
if (this.count < 1) {
setTimeout(function timer(){
this.count++;
console.info("awesome?");
}.bind(this),100)
};
}
}
obj.cool(); //awesome?
6、关于指向函数自身
A:如果要是从函数对象内部引用它自身,那只使用this是不够的,一般来说,你需要通过一个指向函数对象的词法标识符(变量)来引用,例如以下例子:
function foo(){
foo.count = 4 ; //foo指向自身
} setTimeout(function(){
//匿名(没有名字)的函数无法指向自身
},10);
第一个函数称为具名函数,在他内部可以使用foo来引用自身
第二个函数中没哟名称标识符(匿名函数),因此无法从函数内部引用自身
B:arguments.callee已经弃用,不应该再使用
C:使用foo标识符替代this引用函数对象
function foo(num){
foo.count++;
}
foo.count = 0;
var i; for(i = 0 ; i < 10 ; i++){
if (i > 5) {
foo(i)
};
}
console.info(foo.count); //
该方法回避了this问题,并且完全依赖于变量foo的词法作用域
D:强制this指向函数对象
function foo(num){
this.count++;
}
foo.count = 0;
var i; for(i = 0 ; i < 10 ; i++){
if (i > 5) {
foo.call(foo,i);
};
}
console.info(foo.count); //
7、this绑定
A:在严格模式下,this的默认绑定是undefined,在非严格模式下,this的默认绑定是全局对象
function foo(){
"use strict";
console.info(this.a);
}
var a = 2;
foo(); //TypeError : this is undefined function foo(){
console.info(this.a);
}
var a = 2 ;
(function(){
"use strict";
foo(); //
})();
注意:foo的运行环境不是在严格模式下,严格模式下调用foo不影响默认绑定
B:隐式绑定:需要考虑调用位置是否含有上下文对象,或者说被某个对象所拥有或包含
function foo(){
console.info(this.a);
}
var obj = {
a : 2,
foo : foo
}
obj.foo(); //
调用foo的时候,this被绑定到obj,所以上下文中的this都是一样的
注意:对象属性引用链中只有上一层或者说最后一层在调用位置上面起作用,举例来说:
function foo(){
console.info(this.a);
}
var obj2 = {
a : 42,
foo : foo
}
var obj1 = {
a : 2,
obj2 : obj2
}
obj1.obj2.foo(); //
C:隐式丢失
function foo(){
console.info(this.a)
}
var obj = {
a : 2,
foo : foo
}
var bar = obj.foo;
var a = "oops";
bar(); //"oops"
bar其实是对foo函数本身的引用,因此此时bar()其实是一个不带任何修饰的函数调用,函数作为参数传递也是一样的
D:显示绑定
function foo(){
console.info(this.a);
}
var obj = {
a : 2
}
var bar = function(){
foo.call(obj)
}
bar(); //
setTimeout(bar,100); //
//硬绑定的bar不可能再修改它的this
bar.call(window); //
另一种方式是创建一个包裹函数,负责接收参数并返回值
function foo(something){
console.info(this.a,something);
return this.a + something;
}
var obj = {
a : 2
}
var bar = function(){
return foo.apply(obj,arguments);
}
var b = bar(3) //2 3
console.info(b) //
另一种方法是创建一个可以重复使用的辅助函数
function foo(something){
console.info(this.a,something);
return this.a + something;
}
function bind(fn,obj){
return function(){
return fn.apply(obj,arguments);
}
}
var obj = {
a : 2
}
var bar = bind(foo,obj);
var b = bar(3); //2 3
console.info(b) //
另一种方法是bind
function foo(something){
console.info(this.a,something);
return this.a + something;
}
var obj = {
a : 2
}
var bar = foo.bind(obj);
var b = bar(3); // 2 3
console.info(b) //
另一种方法是api调用的上下文
function foo(el){
console.info(el,this.id);
}
var obj = {
id : "awesome"
}
[1,2,3].forEach(foo,obj);
//1 awesome 2 awesome 3 awesome
E:new绑定
function foo (a) {
this.a = a;
}
var bar = new foo(2);
console.info(bar.a); //
F:显示绑定的优先级高于隐式绑定;new绑定的优先级高于显示绑定
8、对象 -- 可计算属性名(ES6)
var prefix = "foo";
var myObject = {
[prefix + "bar"] : "hello",
[prefix + "baz"] : "world"
}
myObject["foobar"]; //hello
myObject["foobaz"]; //world
9、对象 -- 浅复制(ES6)
function anotherFunction(){}
var anotherObject = {
c : true
}
var anotherArray = [];
var myObject = {
a : 2,
b : anotherObject,
c : anotherArray,
d : anotherFunction
}
//执行浅复制
var newObj = Object.assign({},myObject);
newObj.a; //
newObj.b === anotherObject ; //true
注意:Object.assign()使用的是=操作符,所有源对象属性的一些特性(比如writable)不会被复制到目标对象
深复制与浅复制:浅复制是复制出的新对象还是引用,深复制还需要复制引用的函数
10、数组遍历 --- ES6
var myArray = [1,2,3];
for(var v of myArray){
console.info(v);
}
//
//
//
直接遍历数组的值而不是数组下标
原理:每次都会调用next()方法,该方法可以进行数组、对象……的遍历,不仅仅只是遍历数组而已
11、对象属性设置与屏蔽 --- ES6
var anotherObject = {
a : 2
} var myObject = Object.create("anotherObject"); anotherObject.a; //= 2
myObject.a; //= 2 anotherObject.hasOwnProperty("a"); //true
myObject.hasOwnProperty("a"); //false myObject.a++; //隐式屏蔽 anotherObject.a; //
myObject.a; //
myObject.hasOwnProperty("a"); //true
myObject.a++ 看起来应该是查找并增加anotherObject.a属性,但是++操作相当于myObject.a = myObject.a + 1.所以++操作首先会通过[[Prototype]]查找属性a并从anotherObject.a中
获取当前属性值2,然后给这个值+1,接着用[[put]]将值3赋给myObject中新建的屏蔽属性a 12、创建一个合适的关联对象
要创建一个合适的关联对象,我们必须使用Object.create(),而不是使用具有副作用的Foo(),这样做的唯一缺点就是需要创建一个新对象,然后把旧对象抛弃掉,不能直接修改已有的默认对象。 在ES-6之前,修改对象的[[prototype]]关联,我们只能通过设置._proto_属性实现,但是该方法并不是标准,并且无法兼容所有浏览器。
ES-6添加了辅助函数Object.setPrototypeOf(..)
//ES-6之前
Bar.prototype = Object.create(Foo.prototype); //ES-6之后
Object.setPrototypeOf(Bar.prototype,Foo.prototype);
《你不知道的JavaScript -- 上卷》笔记 --- 基于ES6新标准的更多相关文章
-
你不知道的JavaScript上卷笔记
你不知道的JavaScript上卷笔记 前言 You don't know JavaScript是github上一个系列文章 初看到这一标题的时候,感觉怎么老外也搞标题党,用这种冲突性比较强的题目 ...
-
【你不知道的javaScript 上卷 笔记3】javaScript中的声明提升表现
console.log( a ); var a = 2; 执行输出undefined a = 2; var a; console.log( a ); 执行输出2 说明:javaScript 运行时在编 ...
-
【你不知道的javaScript 上卷 笔记7】javaScript中对象的[[Prototype]]机制
[[Prototype]]机制 [[Prototype]]是对象内部的隐试属性,指向一个内部的链接,这个链接的作用是:如果在对象上没有找到需要的属性或者方法引用,引擎就 会继续在 [[Prototyp ...
-
【你不知道的javaScript 上卷 笔记6】javaScript中的对象相关内容
一.创建一个对象的语法 var myObj = { key: value // ... };//字面量 var myObj = new Object(); //new myObj.key = valu ...
-
【你不知道的javaScript 上卷 笔记5】javaScript中的this词法
function foo() { console.log( a ); } function bar() { var a = 3; foo(); } var a = 2; bar(); 上面这段代码为什 ...
-
【你不知道的javaScript 上卷 笔记4】javaScript 中闭包的一些运用
什么是闭包 闭包是javaScript语言的一种特性,在 javaScript 中以函数作为承接单元.当函数可以记住并访问所在的词法作用域时,就产生了闭包,即使函数是在当前词法作用域之外执行. fun ...
-
【你不知道的javaScript 上卷 笔记2】 javaScript 的作用域规则
一.什么是词法作用域? 词法作用域是在定义词法阶段的作用域,就是由代码变量和作用域块写在哪里决定的,基本上词法分析器在处理代码时会保持作用域不变. 二.词法作用域特点 完全由写代码期间函数所声明的位置 ...
-
【你不知道的javaScript 上卷 笔记1】 javaScript 是如何工作的?
一.什么是作用域? 作用域是用来存储变量以及方便寻找变量的一套规则. 二.javaScript 编译过程(编译发生在代码执行前的几微妙) 分词/词法分析(Tokenizing/Lexing)-> ...
-
《你不知道的 JavaScript 上卷》 学习笔记
第一部分: 作用域和闭包 一.作用域 1. 作用域:存储变量并且查找变量的规则 2. 源代码在执行之前(编译)会经历三个步骤: 分词/此法分析:将代码字符串分解成有意义的代码块(词法单元) 解析/语法 ...
随机推荐
-
不制作证书是否能加密SQLSERVER与客户端之间传输的数据?
不制作证书是否能加密SQLSERVER与客户端之间传输的数据? 在做实验之前请先下载network monitor抓包工具 微软官网下载:http://www.microsoft.com/en-us/ ...
- flume ng配置拓扑图
-
springMVC从上传的Excel文件中读取数据
示例:导入客户文件(Excle文件) 一.编辑customer.xlsx 二.在spring的xml文件设置上传文件大小 <!-- 上传文件拦截,设置最大上传文件大小 10M=10*1024*1 ...
-
hdoj 1028 Ignatius and the Princess III(区间dp)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1028 思路分析:该问题要求求出某个整数能够被划分为多少个整数之和(如 4 = 2 + 2, 4 = 2 ...
-
输入身份证号码自动读取生日与性别(delphi)
一.格式介绍: [15位号码格式] 1.第l一6位数为行政区划代码; 2.第7-12位数为出生日期代码; 3.第13---15位数为分配顺序代码; (1).行政区划代码,是指公民第一次申领居民身份证时 ...
-
nginx启动,重启,关闭
1.nginx启动: a. /usr/path/sbin/nginx -c [/etc/path/nginx.conf] 中括号中为指定加载的配置文件,不指定则加载默认配置文件 b. ...
-
.net core2.0半年的使用经验之前言
目录 前言 使用dapper做数据层调用 使用T4模板生成 使用缓存 使用swagger做接口文档(非restful) 使用identity做身份认证 使用jwt做身份认证 使用CORS跨域 调用we ...
-
SNMP源码分析之(一)配置文件部分
snmpd.conf想必不陌生.在进程启动过程中会去读取配置文件中各个配置.其中几个参数需要先知道是干什么的: token:配置文件的每行的开头,例如 group MyROGroup v1 readS ...
-
HDU 1520 树形DP入门
HDU 1520 [题目链接]HDU 1520 [题目类型]树形DP &题意: 某公司要举办一次晚会,但是为了使得晚会的气氛更加活跃,每个参加晚会的人都不希望在晚会中见到他的直接上司,现在已知 ...
-
scrapy框架初级
scrapy入门教程:https://scrapy-chs.readthedocs.io/zh_CN/0.24/intro/tutorial.html 一.安装 python模块网站,应用文件放置在s ...