Truthy 与 Falsy
falsy 值 (虚值) 是在 Boolean上下文中认定为 false 的值。
JavaScript在需要用到布尔类型值的上下文中使用强制类型转换(Type Conversion)将值转换为布尔值,例如条件语句和循环语句。
js只有8个Falsy值(false,0,-0,0n(当BigInt作为布尔值使用时, 遵从其作为数值的规则. 0n 是 falsy值.),空字符串("", '', ``),null,undefined,NaN),其它均为Truthy值。
数组常用方法
1.push(末尾添加一个或多个元素(,隔开),返回新长度) / pop(删除并返回最后一个元素)
2.unshift(开头添加一个或多个元素(,隔开),返回新长度) / shift(删除并返回第一个元素)
3.every(所有元素符合条件才返回true) / some(一个元素符合条件就返回true)
let ages = [32, 33, 16, 40];
function checkAdult(age) {
return age >= 18;
}
console.log(ages.every(checkAdult)); //false 并非所有age都大于等于18
4.indexOf(正序搜索元素并返回第一个匹配位置) / lastIndexOf(倒序搜索元素并返回倒序的第一个匹配位置) / includes(检查数组是否包含指定的元素返回boolean)
5.reduce(将数组的值处理为单个值(从左到右),不改变原始数组) / forEach(为每个数组元素调用函数) / map(为每个数组元素调用函数的结果创建新数组,不改变原始数组) / filter(数组中通过测试的每个元素创建新数组,不改变原始数组)
// 4个例子各种单独运行
// reduce
let numbers = [175, 50, 25];
function myFunc(total, num) {
return total - num;
}
console.log(numbers.reduce(myFunc)); //100
// forEach
let text = "";
const fruits = ["apple", "orange", "cherry"];
function myFunction(item, index) {
text += index + ": " + item + "<br>";
}
fruits.forEach(myFunction);
console.log(text);// 0: apple<br>1: orange<br>2: cherry<br>
// map
const numbers = [4, 9, 16, 25];
console.log(numbers.map(Math.sqrt)); //[ 2, 3, 4, 5 ]
// filter
let ages = [32, 33, 16, 40];
function checkAdult(age) {
return age >= 18;
}
console.log(ages.filter(checkAdult)); //[ 32, 33, 40 ]
6.slice(选择数组的一部分(从给定的start参数(包括,可选,没有则起复制作用)开始的元素,并在给定的end参数(不包括,可选,没有则起复制到尾)处结束),不改变原始数组返回新数组) / splice(从数组中添加/删除元素(参数:index-必需,指定在什么位置添加/删除项目,howmany-可选,要删除的项目数,item1, ..., itemX -可选,要添加到数组中的新元素),改变原始数组返回删除项目)
// slice
var fruits = ["Banana", "Orange", "Lemon", "Apple", "Mango"];
console.log(fruits.slice(1, 3)); //[ 'Orange', 'Lemon' ]
// splice
let fruits = ["Banana", "Orange", "Apple", "Mango"];
fruits.splice(2, 1, "Lemon", "Kiwi");
console.log(fruits); //[ 'Banana', 'Orange', 'Lemon', 'Kiwi', 'Mango' ]
7.entries(返回键/值对数组迭代(Array Iterator)对象,不改原始数组) / keys(返回 Array Iteration 对象,包含原始数组的键)
// entries
const fruits = ["Banana", "Orange", "Apple", "Mango"];
const f = fruits.entries();
console.log(f); //Object [Array Iterator] {}
for (let x of f) {
console.log(x); //[ 0, 'Banana' ],[ 1, 'Orange' ],[ 2, 'Apple' ],[ 3, 'Mango' ]
}
// keys
let fruits = ["Banana", "Orange", "Apple", "Mango"];
let fk = fruits.keys();
console.log(fk) // Object [Array Iterator] {}
for (let x of fk) {
console.log(x); // 0,1,2,3
}
8.join(将数组的所有元素连接成一个字符串,不改变原始数组)
9.sort(对数组的元素进行排序,改变原始数组) / reverse(反转数组中元素的顺序,改变原始数组)
// sort
const points = [40, 100, 1, 5, 25, 10];
points.sort(function(a, b){return b-a});
console.log(points); //[ 100, 40, 25, 10, 5, 1 ]
对象常用方法
1.创建对象与修改原型链:
- Object.create(proto,[propertiesObject])(创建一个新对象,使用现有的对象来提供新创建的对象的__proto__。proto-新创建对象的原型对象。propertiesObject-可选。需要传入一个对象,该对象的属性类型参照[
Object.defineProperties()方法]的第二个参数。) - Object.assign(target, ...sources)(target-目标对象。sources-源对象。目标对象与源对象具有相同的键时,目标对象属性将被源对象的属性覆盖。)
- Object.setPrototypeOf(obj, prototype)(obj-要设置其原型的对象。prototype-该对象的新原型(一个对象或null)设置一个指定的对象的原型 ( 即, 内部[[Prototype]]属性)到另一个对象或null。)
// Object.create
const person = {
isHuman: false,
printIntroduction: function () {
console.log(`My name is ${this.name}. Am I human? ${this.isHuman}`);
}
};
const me = Object.create(person);
const she = Object.create({}, { p: { value: 42 } })
me.name = 'Matthew';
me.isHuman = true;
me.printIntroduction();// expected output: "My name is Matthew. Am I human? true"
console.log('she',she) //she {p: 42}
console.log(me) //{name: 'Matthew', isHuman: true}
console.log(me.__proto__) //{isHuman: false, printIntroduction: ƒ}
// Object.assign
const obj = {
a: 1
};
const copy = Object.assign({
a: 2,
b: 2
}, obj);
console.log(copy); // {a: 1, b: 2}
// Object.setPrototypeOf
var dict = Object.setPrototypeOf({}, null);
2.获取对象属性
- Object.keys(obj)(obj-遍历对象,返回一个所有元素为字符串的数组,其元素来自于从给定的
object上面可直接枚举的属性。这些属性的顺序与手动遍历该对象属性时的一致。) - Object.values(obj)(obj-遍历对象,返回一个给定对象自身的所有可枚举属性值的数组,值的顺序与使用for...in循环的顺序相同 ( 区别在于 for-in 循环枚举原型链中的属性 )。)
- Object.entries(obj)(返回一个给定对象自身可枚举属性的键值对数组,其排列与使用for...in循环遍历该对象时返回的顺序一致(区别在于 for-in 循环还会枚举原型链中的属性)。)
- Object.getOwnPropertyNames(obj)(返回一个数组,该数组对元素是
obj自身拥有的枚举或不可枚举属性名称字符串。数组中枚举属性的顺序与通过for...in循环(或Object.keys)迭代该对象属性时一致。数组中不可枚举属性的顺序未定义。与Object.keys区别是会加带出不可枚举属性名称字符串) - Object.getOwnPropertySymbols(obj)(返回一个给定对象自身的所有 Symbol 属性的数组。)
var obj = { 0: 'a', 'kk': 'kk', 2: 'c'};
Object.defineProperty(obj,'jj',{
value: 'jj',
enumerable: false,
})
obj[Symbol("oo")] = "Symboloo";
console.log(Object.keys(obj)); // ['0', '2', 'kk']
console.log(Object.values(obj)); // ['a', 'c', 'kk']
console.log(Object.entries(obj)); // [['0', 'a'],['2', 'c'],['kk', 'kk']]
for (const [key, value] of Object.entries(obj)) {
console.log(`${key}: ${value}`); // 0: a // 2: c // kk: kk
}
console.log(Object.getOwnPropertyNames(obj)); // ['0', '2', 'kk', 'jj']
console.log(Object.getOwnPropertySymbols(obj)); //[Symbol(oo)]
3.修改对象属性
- Object.defineProperty(obj, prop, descriptor)(直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象。查看之前详细记录(juejin.cn/post/705411…
- Object.defineProperties(obj, props)(obj-在其上定义或修改属性的对象。props-要定义其可枚举属性或修改的属性描述符的对象。)
// Object.defineProperty
const object1 = {};
Object.defineProperty(object1, 'property1', {
value: 42,
writable: false
});
object1.property1 = 77; // 修改不了
console.log(object1.property1); //42
// Object.defineProperties
var obj = {};
Object.defineProperties(obj, {
'property1': {
value: true,
writable: true
},
'property2': {
value: 'Hello',
writable: false
}
// etc. etc.
});
console.log(obj) //{property1: true, property2: 'Hello'}
4.获取对象的属性描述符
- Object.getOwnPropertyDescriptors(obj)(获取一个对象的所有自身属性的描述符。)
- Object.getOwnPropertyDescriptor(obj, prop)(obj-需要查找的目标对象,prop-目标对象内属性名称,返回指定对象上一个自有属性对应的属性描述符。(自有属性指的是直接赋予该对象的属性,不需要从原型链上进行查找的属性))
const object1 = {
property1: 42,
property2: 43,
};
console.log(Object.getOwnPropertyDescriptors(object1))
//{property1:{configurable: true,enumerable: true,value: 42,writable: true},property2:{configurable: true,enumerable: true,value: 43,writable: true}}
console.log(Object.getOwnPropertyDescriptor(object1, 'property1')) //{value: 42, writable: true, enumerable: true, configurable: true}
5.冻结,密封,不可拓展对象
- Object.freeze(obj)(obj-要被冻结的对象。被冻结对象自身的所有属性都不可能以任何方式被修改。)
- Object.isFrozen(obj)(obj-检测对象,返回BOOLEAN。一个对象是冻结的是指它不可扩展,所有属性都是不可配置的,且所有数据属性(即没有getter或setter组件的访问器的属性)都是不可写的。)
- Object.seal(obj)(obj-要被密封的对象。通常,一个对象是可扩展的(可以添加新的属性)。密封一个对象会让这个对象变的不能添加新属性,且所有已有属性会变的不可配置。)
- Object.isSealed(obj)(如果这个对象是密封的,则返回
true,否则返回false。密封对象是指那些不可扩展的,且所有自身属性都不可配置且因此不可删除(但不一定是不可写)的对象。) - Object.preventExtensions(obj)(让一个对象变的不可扩展,也就是永远不能再添加新的属性。)
- Object.isExtensible(obj)(判断一个对象是否是可扩展的(是否可以在它上面添加新的属性)。)
// Object.freeze / Object.isFrozen
const obj = {
prop: 42
};
Object.freeze(obj);
obj.prop = 33; // 修改不了
console.log(obj.prop); // 42
console.log(Object.isFrozen(obj)) //true
// Object.preventExtensions / Object.isExtensible
const object1 = {};
Object.preventExtensions(object1);
try {
Object.defineProperty(object1, 'property1', {
value: 42
});
} catch (e) {
console.log(Object.isExtensible(object1)); //false
console.log(e);// TypeError: Cannot define property property1, object is not extensible
}
6.其它
- Object.is(value1,value2)(判断两个值是否为同一个值。)
//Object.is
let value1 = {a:1}
let value2 = {a:1}
let value3 = value1;
console.log(Object.is(value1, value2)); //false
console.log(Object.is(value1, value3)); //true
var, let 和 const 区别
var: var用于创建一个可变变量,存在变量声明提升。
const: 它用于创建一个不可变变量,不可变变量是指其值在程序的整个生命周期中永不改变的变量。
let: let用于创建一个可变变量,可变变量是像var这样的普通变量,可以任意次数地更改。
注意点:如用const声明person对象,给age重新赋值是没问题的
但是重新给person赋值是不可以的
- const声明的是常量,必须赋值
1)一旦声明必须赋值,不能使用null占位。
2)声明后不能再修改
3)如果声明的是复合类型数据,可以修改其属性 - let和var声明的是变量,声明之后可以更改,声明时可以不赋值
- var允许重复声明变量,后一个变量会覆盖前一个变量。let和const在同一作用域不允许重复声明变量,会报错。
- var声明的变量存在变量提升(将变量提升到当前作用域的顶部)。即变量可以在声明之前调用,值为undefined。let和const不存在变量提升。即它们所声明的变量一定要在声明后使用,否则报ReferenceError错。
- var不存在块级作用域。let和const存在块级作用域。ES5中作用域有:全局作用域、函数作用域。没有块作用域的概念。ES6(简称ES6)中新增了块级作用域。块作用域由 { } 包括,if语句和for语句里面的{ }也属于块作用域。
注意点:
for in 与for of区别
- for of 循环用来获取一对键值对中的值,而
for...in获取的是键名 - 一个数据结构只要部署了 Symbol.iterator 属性, 就被视为具有 iterator接口, 就可以使用 for of循环。