《你不知道的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. 源代码在执行之前(编译)会经历三个步骤: 分词/此法分析:将代码字符串分解成有意义的代码块(词法单元) 解析/语法 ...
 
随机推荐
- Structure And Representation Of MIB Object Names - SNMP Tutorial
			
30.8 Structure And Representation Of MIB Object Names We said that ASN.1 specifies how to represent ...
 - ajax 的返回值类型
			
ajax的dataType类型有三种:text,json,xml. text类型: 主页面: $.ajax({ url:"chuli.php", dataType:&quo ...
 - 牛顿法|阻尼牛顿法|拟牛顿法|DFP算法|BFGS算法|L-BFGS算法
			
一直记不住这些算法的推导,所以打算详细点写到博客中以后不记得就翻阅自己的笔记. 泰勒展开式 最初的泰勒展开式,若 在包含 的某开区间(a,b)内具有直到n+1阶的导数,则当x∈(a,b)时,有: ...
 - 创建一个点状注记(MarkerElement)
			
1.根据XY创建一个点 /// <summary> /// 根据x y创建新点 /// </summary> /// <param name="dX" ...
 - 使用Nominatim进行openstreetmap地址搜索/解析
			
Nominatim(来自拉丁语,意思是“名称”)是一个可以按名称和地址来搜索OSM中的数据,并生成OSM点的合成地址的工具(反向地理编码).可用在http://nominatim.openstreet ...
 - css3过渡效果
 - java基本知识小记(1)
			
1.Java中的值传递 值传递意味着对于传给方法的每个参数都会制作一份副本然后将副本而不是原始值传递给方法并且通过参数的名进行引用. 注意:虽然传值机制对于所有参数类型都适用,但是他对对象类型的作用与 ...
 - PHP数组函数: array_walk()
			
定义和用法 array_walk() 函数对数组中的每个元素应用回调函数.如果成功则返回 TRUE,否则返回 FALSE. 典型情况下 function 接受两个参数.array 参数的值作为第一个, ...
 - Fragment间的通信
			
在网上看到的一篇文章,总结的很好 为了重用Fragment的UI组件,创建的每个Fragment都应该是自包含的.有它自己的布局和行为的模块化组件.一旦你定义了这些可重用的Fragment,你就可以把 ...
 - AJAX工作原理及其优缺点
			
1.什么是AJAX?AJAX全称为"Asynchronous JavaScript and XML"(异步JavaScript和XML),是一种创建交互式网页应用的网页开发技术.它 ...