《你不知道的JavaScript -- 上卷》笔记 --- 基于ES6新标准
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. 源代码在执行之前(编译)会经历三个步骤: 分词/此法分析:将代码字符串分解成有意义的代码块(词法单元) 解析/语法 ...
随机推荐
- 【原】十张javascript思维导图
下面附上十张javascript思维导图,如果把里面的内容全部掌握,那就是高手了.思维导图提供给我们一个整体的知识体系,也可以说是一种工具,废话不多说,上图: 1.javascript数据类型 2.j ...
- 树莓派2系统DietPi简单安装配置使用介绍
DietPi在Raspberrypi.org上的原帖:http://dwz.cn/HSrmY 版本发布很频繁,给原作者们点个赞.功能会越来越多,而且作者的定制观点很明确,适合树莓派的使用. 之前关于D ...
- yii2 composer安装
安装Yii2 1.安装composer 在命令行输入 curl-sS https://getcomposer.org/installer | php mv composer.phar /usr/loc ...
- Win7 64位下PowerDesigner连接64位Oracle11g数据库
操作系统:WIN7 64旗舰版 Oracle版本:64位11g PowerDesigner版本:15.1 问题描述:因为PowerDesigner是32的程序,连接数据库会默认开启32位的ODBC,因 ...
- MVVM开发模式简单实例MVVM Demo
本文主要是翻译Rachel Lim的一篇有关MVVM模式介绍的博文 A Simple MVVM Example 并具体给出了一个简单的Demo(原文是以WPF开发的,对于我自己添加或修改的一部分会用红 ...
- angularjs中父,子,兄之间controller值得传递
使用angularjs,发现controller间的值传递,比较麻烦的,以后几篇文章会陆续说几种方法. 一,angularjs $broadcast $emit $on的处理思想 在一个control ...
- cf126b(kmp好题)
http://codeforces.com/contest/126/problem/B #include<bits/stdc++.h> using namespace std; const ...
- mac 上的 python
1.mac 上的 python 自己感觉很乱 1.额外安装的 自带的 python27-apple /System/Library/Frameworks/Python.framework/Versio ...
- C和指针 第十四章 预处理器 头文件
编写一个C程序,第一个步骤称为预处理,预处理在代码编译之前,进行一些文本性质的操作,删除注释.插入被include的文件.定义替换由#define定义的符号,以及确定代码的部分内容是否应该按照条件编译 ...
- windows系统和ubuntu虚拟机之间文件共享——samba
参考:http://www.cnblogs.com/phinecos/archive/2009/06/06/1497717.html 一. samba的安装: sudo apt-get insall ...