目录
Array.from(arrayLike[, mapFn[, thisArg]])
常用扩展
对象扩展
对象简写
ES6中规定可以直接在对象中写入变量和函数作为对象的属性和方法,此时属性名为变量名, 属性值为变量的值。对象简写在未来的使用频率极其高。
let name= 'terry'; let foo= { name, //属性简写 sayName(){ //方法简写 console.log('my name is',this.name); } };
对象API拓展
ES6中对于Object的拓展主要是静态方法的拓展。
Object.is()
Object.is() 方法判断两个值是否为同一个值。
语法: Object.is(value1, value2);
参数:
value1 被比较的第一个值。
value2 被比较的第二个值。
返回值:
返回一个 Boolean 类型标示两个参数是否是同一个值。使用Object.is(value1,value2)方法,返回true,或者false。与== 运算不同,== 运算符在判断相等前对两边的变量(如果它们不是同一类型) 进行强制转换 (这种行为的结果会将 "" == false 判断为 true), 而 Object.is不会强制转换两边的值。与=== 运算也不相同,=== 运算符 (也包括 == 运算符) 将数字 -0 和 +0 视为相等,而将Number.NaN 与NaN视为不相等。
Object.is('foo', 'foo'); // true Object.is(window, window); // true Object.is('foo', 'bar'); // false Object.is([], []); // false let foo = { a: 1 }; let bar = { a: 1 }; Object.is(foo, foo); // true Object.is(foo, bar); // false Object.is(null, null); // true console.log(1 === 1);//true console.log(Object.is(1, 1));//true console.log(Object.is(1, 2)); //false console.log(+0 === -0); //true // 特例 console.log(Object.is(+0, -0)); //false console.log(0 === -0); //true console.log(Object.is(0, -0)); //false console.log(NaN === NaN); //false console.log(Object.is(NaN, NaN)); //true console.log(isNaN(NaN)); //true console.log(NaN === 0/0); //false console.log(Object.is(NaN, 0/0)); //true
Object.assign()
Object.assign(target, ...sources) 方法用于将所有可枚举属性的值从一个或多个源对象分配到目标对象。它将返回目标对象。 语法: Object.assign(target, ...sources) 参数: target 目标对象 sources 源对象,可以为一个或多个 如果目标对象中的属性具有相同的键,则属性将被源对象中的属性覆盖。后面的源对象的属性将类似地覆盖前面的源对象的属性。 Object.assign 方法只会拷贝源对象自身的并且可枚举的属性到目标对象。该方法使用源对象的[[Get]]和目标对象的[[Set]],所以它会调用相关 getter 和 setter。因此,它分配属性,而不仅仅是复制或定义新的属性。如果合并源包含getter,这可能使其不适合将新属性合并到原型中。为了将属性定义(包括其可枚举性)复制到原型,应使用Object.getOwnPropertyDescriptor()和Object.defineProperty()。
Tip:深拷贝问题,针对深拷贝,需要使用其他办法,因为 Object.assign()拷贝的是(可枚举)属性值。假如源值是一个对象的引用,它仅仅会复制其引用值。
const target = { a: 1, b: 2 }; const source = { b: 4, c: 5 }; const returnedTarget = Object.assign(target, source); console.log(target); // Object { a: 1, b: 4, c: 5 } console.log(returnedTarget); // Object { a: 1, b: 4, c: 5 }
拓展:自定义深拷贝(不做授课要求)
let obj = {}; let obj1 = { name:'zhangsan', age:12, friends:[1,2,3], count:{ time:'2019-09-09' } }; let obj2 = { name:'lisi', gender:'男', sayName:function(){} }; Object.assign(obj,obj1,obj2); console.log(obj); console.log(obj.sayName===obj2.sayName); //true // 数组 console.log(obj.friends===obj1.friends); //true // 对象 console.log(obj.count===obj1.count); //true //自定义深拷贝,函数可以复用,数组和对象深拷贝 function myClone(target,...tail){ // tail是一个数组,里面是对象 tail.forEach(function(item){ // item 是一个一个的对象 for(let key in item){ if((Array.isArray(item[key])) || (item[key].constructor===Object)){ target[key] = JSON.parse(JSON.stringify(item[key])); }else{ target[key] = item[key]; } } }); return target; } myClone(obj,obj1,obj2); console.log(obj); //函数的浅复制 console.log(obj.sayName===obj2.sayName); //true // 数组 console.log(obj.friends===obj1.friends); //false // 对象 console.log(obj.count===obj1.count); //false
Object.getPrototypeOf()
Object.getPrototypeOf() 方法返回指定对象的原型(内部[[Prototype]]属性的值)。
语法:
Object.getPrototypeOf(object)
参数:
obj 要返回其原型的对象。
返回值:
返回给定对象的原型,如果没有继承属性,则返回 null 。
let obj = {}; // 获取obj的原型对象 console.log(Object.getPrototypeOf(obj)); // 打印出:obj的原型对象 console.log(Object.getPrototypeOf(obj)===Object.prototype); //打印出:true console.log(Object.getPrototypeOf(obj)===obj.__proto__); //打印出:true
Object.setPrototypeOf()
Object.setPrototypeOf() 方法设置一个指定的对象的原型 ( 即, 内部[[Prototype]]属性)到另一个对象或 null。
语法:
Object.setPrototypeOf(obj, prototype)
参数:
obj 要设置其原型的对象
prototype 该对象的新原型(一个对象 或 null).
let obj = {}; // 获取obj的原型对象 console.log(Object.getPrototypeOf(obj)); // 打印出:obj的原型对象 console.log(Object.getPrototypeOf(obj)===Object.prototype); //打印出:true console.log(Object.getPrototypeOf(obj)===obj.__proto__); //打印出:true
Object.setPrototypeOf()
Object.setPrototypeOf() 方法设置一个指定的对象的原型 ( 即, 内部[[Prototype]]属性)到另一个对象或 null。
语法:
Object.setPrototypeOf(obj, prototype)
参数:
obj 要设置其原型的对象
prototype 该对象的新原型(一个对象 或 null).
let dict = Object.setPrototypeOf({}, null);
Tip:由于现代 JavaScript 引擎优化属性访问所带来的特性的关系,更改对象的 [[Prototype]]在各个浏览器和 JavaScript 引擎上都是一个很慢的操作。其在更改继承的性能上的影响是微妙而又广泛的,这不仅仅限于 obj.proto = ... 语句上的时间花费,而且可能会延伸到任何代码,那些可以访问任何[[Prototype]]已被更改的对象的代码。如果你关心性能,你应该避免设置一个对象的 [[Prototype]]。相反,你应该使用 Object.create()来创建带有你想要的[[Prototype]]的新对象。
Object.keys()
Object.keys() 方法获取所有可枚举属性名,会返回一个由一个给定对象的自身可枚举属性组成的数组,数组中属性名的排列顺序和正常循环遍历该对象时返回的顺序一致。 如果你想获取一个对象的所有属性,,甚至包括不可枚举的,使用Object.getOwnPropertyNames()。
语法:
Object.keys(obj)
参数:
obj 要返回其枚举自身属性的对象。
返回值:
返回一个表示给定对象的所有可枚举属性的字符串数组。
// simple array let arr = ['a', 'b', 'c']; console.log(Object.keys(arr)); // 打印出: ['0', '1', '2'] // array like object let obj = { 0: 'a', 1: 'b', 2: 'c' }; console.log(Object.keys(obj)); // 打印出: ['0', '1', '2'] //遍历 Object.keys(obj).forEach((item) => { console.log(item, obj[item]); }) // array like object with random key ordering let anObj = { 100: 'a', 2: 'b', 7: 'c' }; console.log(Object.keys(anObj)); // 打印出: ['2', '7', '100'] // getFoo is a property which isn't enumerable let myObj = Object.create({}, { getFoo: { value: function () { return this.foo; } } }); myObj.foo = 1; console.log(Object.keys(myObj)); // 打印出: ['foo']
Object.values()
Object.values() 方法获取所有的可枚举属性值,返回一个给定对象自身的所有可枚举属性值的数组,值的顺序与使用for...in循环的顺序相同 ( 区别在于 for-in 循环枚举原型链中的属性 )。
语法:
Object.values(obj)
参数:
obj 被返回可枚举属性值的对象。
返回值:
返回一个包含对象自身的所有可枚举属性值的数组。
let obj = { foo: 'bar', baz: 42 }; console.log(Object.values(obj)); // 打印出: ['bar', 42] // array like object let obj = { 0: 'a', 1: 'b', 2: 'c' }; console.log(Object.values(obj)); // 打印出: ['a', 'b', 'c'] // array like object with random key ordering // when we use numeric keys, the value returned in a numerical order according to the keys let an_obj = { 100: 'a', 2: 'b', 7: 'c' }; console.log(Object.values(an_obj)); // 打印出: ['b', 'c', 'a'] // getFoo is property which isn't enumerable let my_obj = Object.create({}, { getFoo: { value: function() { return this.foo; } } }); my_obj.foo = 'bar'; console.log(Object.values(my_obj)); // 打印出: ['bar'] // non-object argument will be coerced to an object console.log(Object.values('foo')); // 打印出: ['f', 'o', 'o']
Object.entries()
Object.entries() 方法获取所有的可枚举属性名和属性值键值对,返回一个给定对象自身可枚举属性的键值对数组,其排列与使用 for...in 循环遍历该对象时返回的顺序一致(区别在于 for-in 循环还会枚举原型链中的属性)。
语法:
Object.entries(obj)
参数:
obj 可以返回其可枚举属性的键值对的对象。
返回值:
给定对象自身可枚举属性的键值对数组
const obj = { foo: 'bar', baz: 42 }; console.log(Object.entries(obj)); // 打印出: [ ['foo', 'bar'], ['baz', 42] ] // array like object const obj2 = { 0: 'a', 1: 'b', 2: 'c' }; console.log(Object.entries(obj)); // 打印出: [ ['0', 'a'], ['1', 'b'], ['2', 'c'] ] // array like object with random key ordering const anObj = { 100: 'a', 2: 'b', 7: 'c' }; console.log(Object.entries(anObj)); // 打印出: [ ['2', 'b'], ['7', 'c'], ['100', 'a'] ] // getFoo is property which isn't enumerable const myObj = Object.create({}, { getFoo: { value() { return this.foo; } } }); myObj.foo = 'bar'; console.log(Object.entries(myObj)); // 打印出: [ ['foo', 'bar'] ] // non-object argument will be coerced to an object console.log(Object.entries('foo')); // 打印出: [ ['0', 'f'], ['1', 'o'], ['2', 'o'] ] // iterate through key-value gracefully const obj3 = { a: 5, b: 7, c: 9 }; for (const [key, value] of Object.entries(obj)) { console.log(`${key} ${value}`); // 打印出: "a 5", "b 7", "c 9" } // Or, using array extras Object.entries(obj).forEach(([key, value]) => { console.log(`${key} ${value}`); // 打印出: "a 5", "b 7", "c 9" });
函数扩展
函数参数
ES6 允许为函数的参数设置默认值,即直接写在参数定义的后面。通常情况下,定义了默认值的参数,应该是函数的尾参数,函数的length属性,将返回没有指定默认值的参数个数。
设置默认值
function log(x, y = 'World') { console.log(x, y); // 打印出:1,'World' } log(1);
参数解构
参数默认值可以与解构赋值的默认值,结合起来使用。
function foo({x, y = 5}) {
函数参数对象解构、数据结构等
function test({ name, age = 1, ...obj }) { console.log(name, age, obj); } test({ name: 'zhangsan', age: 12, gender: 1,weight:40 }); //zhangsan 12 { gender: 1, weight: 40 }
rest 参数
ES6 引入 rest 参数(形式为...变量名),用于获取函数的多余参数得到一个数组,这样就不需要使用arguments对象了。
function add(...values) { console.log(values); // 打印出:[2,5,3] } add(2, 5, 3)
箭头函数
JavaScript中,经常使用回调函数,箭头函数的出现大大简化了回调函数的写法,当然,除了作为函数参数,箭头函数也可以出现在其他地方。
如果箭头函数不需要参数或需要多个参数,就使用一个圆括号代表参数部分。如果箭头函数的代码块部分多于一条语句,就要使用大括号将它们括起来,并且使用return语句返回。
箭头函数里面没有自己的this,而是引用外层作用域中的this。
1.普通函数 -> 谁调用他她指向谁 (特例:延时器,存在延时器作用域里就的考虑它是window全局执行的,只要走到这一步,环境指向就变了) 2.()=>{} 看定义在哪,就指向哪
它与传统的
JavaScript
函数有些不同,具体看下面几点:
没有
this
、super
、arguments
不能通过
new
关键字调用没有原型
prototype
不可以改变
this
指向不支持重复的命名参数
let f = v => v; // 等价于 let f = function(v) { return v; }; let obj = { name:"terry", say1:function(){ console.log(this.name) }, say2() { console.log(this.name) }, say3: () => { console.log(this) //global }, say4() { return () => { console.log(this);//obj } } }; obj.say1(); obj.say2(); obj.say3(); obj.say4()();
数组API拓展
数组在静态方法与实例方法中都有所拓展。
Array.from()
Array.from() 方法将类似数组或可迭代对象转为数组,从一个类似数组或可迭代对象创建一个新的,浅拷贝的数组实例。
Array.from() 可以通过以下方式来创建数组对象: 伪数组对象(拥有一个 length 属性和若干索引属性的任意对象) 可迭代对象(可以获取对象中的元素,如 Map和 Set 等)
语法:
Array.from(arrayLike[, mapFn[, thisArg]])
参数:
arrayLike 想要转换成数组的伪数组对象或可迭代对象。
mapFn 可选 如果指定了该参数,新数组中的每个元素会执行该回调函数。
thisArg 可选 执行回调函数 mapFn 时 this 对象。
返回值:
一个新的数组实例。
Array.from('foo'); // [ "f", "o", "o" ] function f() { return Array.from(arguments); } f(1, 2, 3); // [ 1, 2, 3 ]
Array.of()
Array.of() 方法创建一个具有可变数量参数的新数组实例,而不考虑参数的数量或类型。
Array.of() 和 Array 构造函数之间的区别在于处理整数参数:Array.of(7) 创建一个具有单个元素 7 的数组,而Array(7) 创建一个长度为7的空数组(注意:这是指一个有7个空位(empty)的数组,而不是由7个undefined组成的数组)。
语法:
Array.of(element0[, element1[, ...[, elementN]]])
参数:
elementN 任意个参数,将按顺序成为返回数组中的元素。
返回值:
新的 Array 实例。
Array.of(7); // [7] Array.of(1, 2, 3); // [1, 2, 3] Array(7); // [ , , , , , , ] Array(1, 2, 3); // [1, 2, 3] Array.of(1); // [1] Array.of(1, 2, 3); // [1, 2, 3] Array.of(undefined); // [undefined]
Array.prototype.find()
Array.prototype.find() 方法返获取元素,回数组中满足提供的测试函数的第一个元素的值。否则返回 undefined。
语法:
arr.find(callback[, thisArg])
参数:
callback 在数组每一项上执行的函数,接收3个参数:
item 当前遍历到的元素。
index 可选 当前遍历到的索引。
array 可选 数组本身。
thisArg 可选 执行回调时用作this 的对象。
返回值:
数组中第一个满足所提供测试函数的元素的值,否则返回 undefined。
Array.prototype.findIndex()
Array.prototype.findIndex() 方法找到一个元素在数组中的位置,返回数组中满足提供的测试函数的第一个元素的索引。若没有找到对应元素则返回-1。
语法:
arr.findIndex(callback[, thisArg])
参数:
callback 在数组每一项上执行的函数,接收3个参数:
item 当前遍历到的元素。
index 可选 当前遍历到的索引。
array 可选 数组本身。
thisArg 可选 执行回调时用作this 的对象。
返回值:
数组中通过提供测试函数的第一个元素的索引。否则,返回-1。
//查找等于2的元素 let arr = [10,8,3,2,4,2,5]; //find方法返回第一个满足条件的元素或者undefined let resultNum = arr.find((item, index) => { return item === 2; }); console.log(resultNum);//2 // findIndex返回第一个满足条件的元素的索引或者-1 let resultIdx = arr.findIndex((item, index) => { return item === 2; }); console.log(resultIdx);//3
function isPrime(element, index, array) { let start = 2; while (start <= Math.sqrt(element)) { if (element % start++ < 1) { return false; } } return element > 1; } console.log([4, 6, 8, 12].findIndex(isPrime)); // -1, not found console.log([4, 6, 7, 12].findIndex(isPrime)); // 2
Array.prototype.includes()
Array.prototype.includes() 方法找到一个元素是否存在于数组中,用来判断一个数组是否包含一个指定的值,根据情况,如果包含则返回 true,否则返回false。使用 includes()比较字符串和字符时是区分大小写。
语法:
arr.includes(valueToFind[, fromIndex])
参数:
valueToFind 需要查找的元素值。
fromIndex 可选 从fromIndex 索引处开始查找
valueToFind。如果为负值,则按升序从 array.length + fromIndex 的索引开始搜 (即使从末尾开始往前跳 fromIndex 的绝对值个索引,然后往后搜寻)。默认为 0。如果 fromIndex 大于等于数组的长度,则会返回 false,且该数组不会被搜索。
返回值:
返回一个布尔值 Boolean ,如果在数组中找到了(如果传入了 fromIndex ,表示在 fromIndex 指定的索引范围中找到了)则返回 true 。
1, 2, 3].includes(2); // true [1, 2, 3].includes(4); // false [1, 2, 3].includes(3, 3); // false [1, 2, 3].includes(3, -1); // true [1, 2, NaN].includes(NaN); // true
Array.prototype.fill()
Array.prototype.fill() 方法填充数组,用一个固定值填充一个数组中从起始索引到终止索引内的全部元素。不包括终止索引。
语法:
arr.fill(value[, start[, end]])
参数:
value 用来填充数组元素的值。
start 可选 起始索引,默认值为0。
end 可选 终止索引,默认值为 this.length。
如果 start和end 是个负数, 则开始索引会被自动计算成为 length+start
返回值:
修改后的数组。
let arr = ["a", , "c"]; let sparseKeys = Object.keys(arr); let denseKeys = [...arr.keys()]; console.log(sparseKeys); // ['0', '2'] console.log(denseKeys); // [0, 1, 2]
let arr = [2, 3, 4, 5, 6, 2]; // 遍历 let keys = arr.keys(); console.log(keys); //keys变量当前是迭代器对象 // 遍历迭代器对象 let result; while (!(result = keys.next()).done) { console.log(result); } /* console.log(keys.next());// { value: 0, done: false } console.log(keys.next());// { value: 0, done: false } console.log(keys.next()); console.log(keys.next()); console.log(keys.next()); console.log(keys.next()); console.log(keys.next());//{ value: undefined, done: true } console.log(keys.next());//{ value: undefined, done: true } */ // 迭代器实现了Iterator接口,只要有实现了Iterator接口就可以for-of遍历 for (let key of keys) { console.log(key); }
Array.prototype.values()
Array.prototype.values()方法获取数组元素,返回一个新的 Array Iterator 对象,该对象包含数组每个索引的值。
语法:
arr.values()
返回值:
一个新的 Array 迭代对象。
let arr = ['w', 'y', 'k', 'o', 'p']; let eArr = arr.values(); for (let letter of eArr) { console.log(letter); } //"w" "y "k" "o" "p"
Array.prototype.entries()
Array.prototype.entries() 方法获取数组中的key、value键值对,返回一个新的Array Iterator对象,该对象包含数组中每个索引的键/值对。
语法:
arr.entries()
返回值:
一个新的 Array 迭代器对象。Array Iterator是对象,它的原型(proto:Array Iterator)上有一个next方法,可用用于遍历迭代器取得原数组的[key,value]。
let arr = ["a", "b", "c"]; let iterator = arr.entries(); console.log(iterator); // 打印出:Array Iterator { } for (let letter of iterator) { console.log(letter); } // 打印出: // Array [ 0, "a" ] // Array [ 1, "b" ] // Array [ 2, "c" ]
笔试题:如果想要遍历一个数组,你可以使用什么方法?
1)for/while/do-while/for-in 骑自行车送快递
2)forEach 找人骑自行车送快递
3)迭代器 找顺丰送快递
4)for-of 菜鸟驿站