14.this指向和ES6常用内容

this指向
 
this 是javascript的一个关键字
它代表函数运行时,自动生成的一个内部对象,只能在函数内部使用
随着函数使用场合的不同,this的值会发生变化
但是有一个总的原则,那就是this指的是函数的调用对象或事件的调用对象
注意:找不到调用对象时this指向window对象
 
改变匿名函数的this指向:function (){}.bind(函数体内this指向的对象)
var obj = {name: '隔壁王叔叔',age: 33};
setTimeout(function (){
    console.log(this);
}.bind(obj),1000);
 
改变非匿名函数的this指向:call、apply,如:函数.call(函数体内this指向的对象)
var obj = {name: '隔壁王叔叔',age: 33};
var arr = [1,2,3];
arr.fn = function () {
    console.log(this);
}
arr.fn();
arr.fn.call(obj);
注意:关于call和apply,目前只需了解,后面的课程继续学习!
 
 
ES6常用内容
 
let与const
 
let关键字,用来声明变量,它的用法类似于var。
 
let不允许重复声明变量;
var a = 1;
var a = 2;
console.log(a);
 
let b = 1;
let b = 2;
console.log(b);
 
let声明变量仅在块级作用域内有效;
for (var i = 0; i < 10; i++) {
    console.log(i);
};
alert(i);
 
for (let v = 0; v < 10; v++) {
    console.log(v);
}
alert(v);
 
不能通过let声明和形参相同的变量;
function test(a) {
    let a = 123;
    console.log(a);
}
test(456);
 
let声明变量不会提升;
alert(a); 
var a = 2;
 
alert(b); 
let b = 2;
注意:let声明的变量一定要在声明之后使用,否则报错。
 
暂时性死区;
ES6规定在某个区块中, 一旦用let或const声明一个变量,那么这个区块就变成块级作用域,用let或const声明的变量就“绑定”这个区域,不再受外部的影响。 在该变量声明之前不可以用,在语法上我们叫这种情况为:暂时性死区 (temporal dead zone,简称 TDZ)。
var tmp = 123;
if (true) {
    tmp = 'abc';
    let tmp;
}
上面代码中,存在全局变量tmp,但是块级作用域内let又声明了一个局部变量tmp,导致后者绑定这个块级作用域,所以在let声明变量前,对tmp赋值会报错。
 
let应用:改造选项卡效果
 
 
const关键字,用来声明一个只读的常量。
const与let类似,但是,const常量一旦声明,常量将不能重新赋值!
const AGE = 18;
alert(AGE);
AGE = 20;
alert(AGE);
 
意味着,const一旦声明,就必须立即初始化,不能留到以后赋值!
const AGE;
 
本质:const实际上保证的,并不是值不能改变,而是指向的那个内存地址不能改变。
const FOO = {name: 'xm'};
FOO.age = 18;
console.log(FOO.age);
FOO = {name: 'xh'};
 
注意:为了和变量区分,一般常量用大写字母。
如:const PI = 3.14;
 
arrow functions(箭头函数)
 
定义:( 形参 ) => { 函数体 }
var box = document.getElementById('box');
box.onclick = function () { // ES5
    console.log(this);
}
box.onclick = () => { // ES6
    console.log(this);
}
 
用箭头函数来写比原来的function写法要简洁很多(针对匿名函数使用)。
var reflect = function (value){ //ES5
    return value;
};
let reflect = value => value; //ES6
 
箭头函数与传统的JavaScript函数主要区别在于以下几点:
1.对 this 的关联。函数内部的 this 指向,取决于箭头函数在哪定义,而非箭头函数的调用对象。
var name = 'xh';
var obj = {
    name: 'xm',
    say: () => {
        alert(this.name);
    }
}
obj.say();
 
当我们使用箭头函数时,函数体内的this对象,就是定义时所在的对象,而不是使用时所在的对象。并不是因为箭头函数内部有绑定this的机制,实际原因是箭头函数根本没有自己的this,它的this是继承外面的,因此内部的this就是外层代码块的this。
var box = document.getElementById('box');
box.onclick = function () {
    setTimeout(() => {
        console.log(this);
    },2000);
}
 
2.new 不可用。箭头函数不能使用 new 关键字来实例化对象,不然会报错。
var Test = function () {};
var obj = new Test();
console.log(obj);
 
var Test = () => {};
var obj = new Test(); //Test is not a constructor
 
3.this 不可变。函数内部 this 不可变,在函数体内整个执行环境中为常量。
var obj1 = {
    name: '隔壁王叔叔',
    age: 33
}
setTimeout(() => {
    console.log(this);
}.bind(obj1),1000); //报错
 
4.没有arguments对象。更不能通过arguments对象访问传入参数。
function fn(){
    console.log(arguments[0]);
    console.log(arguments[1]);
}
fn(1,2);
 
var fn = () => {
    console.log(arguments[0]); //报错
}
fn(3);
 
template string((字符串模板)
 
ES6中字符串模板使用反引号 ` ` 表示,字符串模板中可以解析变量和函数,使用 ${ } 解析
var sname = "小错";
function fnAge(){
    return 18;
}
var str = `大家好,我叫${sname},我今年${fnAge()}岁了`;
alert( str );
 
字符串模板非常有用,当我们要插入大段的html内容到文档中时,传统的写法非常麻烦
var box = document.getElementById('box');
var val1 = 11, val2 = 22, val3 = 33;
box.innerHTML = '<ul><li>'+val1+'</li><li>'+val2+'</li><li>'+val3+'</li></ul>';
box.innerHTML = '<ul>'+
                                '<li>'+val1+'</li>'+
                                '<li>'+val2+'</li>'+
                                '<li>'+val3+'</li>'+
                            '</ul>';
 
使用ES6字符串模板:
box.innerHTML = `
    <ul>
        <li>${val1}</li>
        <li>${val2}</li>
        <li>${val3}</li>
    </ul>
`;
 
Destructuring(解构赋值)
 
ES6允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构赋值。
解构赋值:解析解构进行赋值。
 
var x = 10 , y = 20 , z = 30;
 
var cat = 'ken';
var dog = 'lili';
var zoo = {cat: cat, dog: dog};
console.log(zoo);
 
用ES6完全可以像下面这么写:
 
var [x,y,z] = [10,20,30];
var {sname,age} = {age : 10, sname : "xm" }
console.log( sname );
console.log( age );
 
let cat = 'ken';
let dog = 'lili';
let zoo = {cat, dog};
console.log(zoo);
 
反过来可以这么写:
let dog = {type: 'animal', many: 2};
let { type, many} = dog;
console.log(type);
console.log(many);
 
解构赋值可以作用在函数的参数上,让函数参数的值传递顺序改变
function fn( {sname,age} ){
return `大家好我叫${sname},我今年${age}岁了`;
}
console.log( fn( {age:23,sname:"jack"} ) );
 
Array.from( )
 
Array.from:将含有length属性的对象、类数组转成真正的数组。
Array.from(obj, map函数);
第一个参数为要转换的对象,第二个参数为一个函数,可选,类似map函数。
map函数 : 遍历数组--操作数组--返回数组
var arr = [1,2,3,4,5];
var newArr = arr.map( (item) => { return item*2 } );
console.log( newArr );
 
类数组元素集合:
var lis = document.getElementsByTagName("li");
console.log(lis);
lis.push('abc');
console.log(lis);
 
将lis集合(类数组)转成 数组:
lis = Array.from(lis);
console.log( lis )
lis.push('abc');
console.log(lis);
 
将对象转成 数组:
var obj = {
    "0" : 10 ,
    "1" : 20 ,
    "2" : 30 ,
    "length" : 3
};
var arr = Array.from( obj );
console.log( arr );
 
第二个参数是一个匿名函数 实现的是map功能:
var newArr = Array.from( obj , (item) => { return item*2; } )
console.log( newArr );
 
三个点(...)
 
扩展运算符用三个点号表示,其功能是把数组或类数组对象展开成一系列用逗号隔开的参数序列。
console.log(...[1, 2, 3]);
console.log(1, ...[2, 3, 4], 5);
 
var lis = document.getElementsByTagName("li");
console.log([...lis]);
 
其他用法:
var arr1 = [1,2];
var arr2 = [3,4,5];
function addItems(arr, ...items) {
    arr.push(...items);
};
addItems(arr1,...arr2);
console.log(arr1);
 
arr.push(...items) 和 addItems(arr1,...arr2) 函数调用都使用了扩展运算符将数组变为参数序列
注意这行:function addItems(arr, ...items) 这里的三个点并不是扩展运算符,而是 rest运算符
 
rest运算符是三个点,其功能与扩展运算符恰好相反,把逗号隔开的参数序列组合成一个数组
 
var arr = [1,2,3];
function fn(...args) {// rest运算符 组合数组
console.log(args);
};
fn(...arr);// 扩展运算符 展开数组
console.log(...arr);
 
 
Set 和 Map
 
ES6 提供了两种新的数据结构 Set 和 Map。
 
Set 是一个构造函数,用来生成 Set 数据结构,它类似于数组,但是成员的值都是唯一的、没有重复的, 初始化 Set 可以接受一个数组或类数组对象作为参数,也可以创建一个空的 Set:
var s1 = new Set();
var s2 = new Set([1, 2, 3]);
console.log(s1);
console.log(s2);
 
在 Set 中成员的值是唯一的,重复的值自动被过滤掉
var s1 = new Set([1, 2, 2, 3, 1, 4]);
console.log(s1);
 
Set 的一些属性方法:
size:返回成员总数
add(value):添加某个值,返回Set结构本身
delete(value):删除某个值,返回一个布尔值,表示删除是否成功
has(value):返回一个布尔值,表示该值是否为Set的成员
clear():清除所有成员,没有返回值
 
var set = new Set([1,2]);
set.add(3);// 添加成员
console.log(set.size);// 3 成员总数
console.log(set);// Set(3) {1, 2, 3}
set.add([4,5]);// 添加成员
console.log(set.size);// 4 成员总数
console.log(set.has(2));// true 有该成员
console.log(set);// Set(4) {1, 2, 3, [4, 5]}
set.delete(2);// 删除成员
console.log(set);// Set(3) {1, 3, [4, 5]}
console.log(set.has(2));// false 没有该成员
set.clear();// 清除所有成员
console.log(set);// Set(0) {}
 
得益于数据结构 Set 查找更快速高效,但也因为数据结构的内部数据是无序的,无法实现按下标改查,排序等操作
var arr = [1,2,3,'a',4,'b'];
var set = new Set(arr);
console.log(set[0]);// undefined
console.log(set['a']);// undefined
 
遍历 Set 对象
var set = new Set(['a','b','c','d']);
set.forEach((val,key,set)=>{
    console.log('val: '+val);
    console.log('key: '+key);
    console.log(set);
});
 
使用ES6的 for of 遍历
var set = new Set(['a','b','c','d']);
for (const val of set) {
    console.log(val);
}
 
Set 没有类似 get 的方法,怎么取值呢?
可以用上面的遍历取值,或者可以把 Set 转成真正的数组!
 
 
for/of 与 for/in 区别
for/of:遍历值
var arr = [4,5,6,7];
for (var val of arr) {
    console.log(val);//4 5 6 7
}
 
for/in:遍历键
var arr = [4,5,6,7];
for (var key in arr) {
    console.log(key);//0 1 2 3
}
 
 
Map 是一个构造函数,用来生成 Map 数据结构,它类似于对象,也是键值对的集合,但是“键”可以是非字符串, 初始化 Map 需要一个二维数组,或者直接初始化一个空的 Map:
var m1 = new Map();
var m2 = new Map([['a', 123], ['b', 456], [3, 'abc']]);
console.log(m1);
console.log(m2);
 
Map 的一些操作方法:
set(key, value):设置键值对
get(key):获取键对应的值
has(key):是否存在某个键
delete(key):删除某个键值对,返回一个布尔值,表示删除是否成功
 
var map = new Map([['a', 123], ['b', 456], [3, 'abc']]);
map.set('c',789);
console.log(map.get('c')); // 789
console.log(map.has('b')); // true 此key存在
map.delete(3); // true 成功删除key
console.log(map); // Map(3) {"a" => 123, "b" => 456, "c" => 789}
 
遍历 Map 对象
var map = new Map([['a', 123], ['b', 456], [3, 'abc'],['c', 789]]);
map.forEach((val,key,obj)=>{
    console.log('val: '+val);
    console.log('key: '+key);
    console.log(obj);
});
 
当然也可以使用ES6的 for of 遍历
var map = new Map([['a', 123], ['b', 456], [3, 'abc'],['c', 789]]);
for (const [key,val] of map) {
    console.log(key+' : '+val);
}
 
传统 Object 只能用字符串作键,Object 结构提供了“字符串 — 值”的对应
Map 结构提供了“值 — 值”的对应,是一种更完善的 Hash 结构实现
如果你需要“键值对”的数据结构,Map 比 Object 更快速 更高效 更合适。
 
Symbol类型
 
ES5 的对象属性名都是字符串,这容易造成属性名的冲突。
ES6 引入了一种新的原始数据类型 Symbol,表示独一无二的值。
Symbol 是 JavaScript 语言的第七种数据类型。
 
let s = Symbol('xm');
console.log( s );
console.log( typeof s );
 
对象的属性名现在可以有两种类型,一种是原来就有的字符串,另一种就是新增的 Symbol 类型。
var xm = Symbol();
var obj = {
    [xm] : "小明" //对象的属性是Symbol类型
}
 
Symbol类型的属性 取值是 必须 obj[xm] 不能用obj.xm
console.log( obj[xm] );
 
修改symbol类型的属性
obj[xm] = "web前端";
console.log( obj[xm] );
 
Symbol可以用来保护对象的某个属性
var obj = {
    "sname":"小明",
    "skill" : "web"
}
var age = Symbol();
obj[age] = 18;
console.log( obj );
for( var key in obj ){
    console.log(key + " -> " + obj[key] );
}
原文地址:https://www.cnblogs.com/r-mp/p/11093299.html