JavaScript小知识点

1

判断是否为NaN
利用其为唯一不等于自身的值这个特点

function wqd(value) {
    return value !== value;
}

2

同源策略
取决于三个方面
域名 协议 端口

3

nullundefined只有在非严格相等下成立
只有nullundefined两者之间互相等于除此之外不等于任何值

null == undefined // true

4

逻辑运算符

alert(alert(1) || 2 || alert(3));

先显示1后显示2
因为对alert的调用没有返回值或者说返回undefined

5

空值合并运算符
我们将既不是null也不是undefined的值称为已定义
用途是获取第一个已定义的值

6

空值合并运算符和逻辑运算符的区别
前者返回第一个已定义的值后者返回第一个为真的值
另外需要注意的是空值合并运算符禁止与逻辑运算符或逻辑运算符一起使用
除非使用括号明确指定了优先级

7

breakcontinue标签

wqd:
for (let i = 0; i < 3; i++) {
    for (let j = 0; j < 3; j++) {
        if (i === 1 && j === 1) {
            break wqd;
        }
        console.log(i, j); // 0 0, 0 1, 0 2, 1 0
    }
}

8

函数声明函数表达式的区别
区别在于引擎会在什么时候创建函数
函数表达式在代码执行到达时创建并且仅从那一刻起可以调用
函数声明在被定义之前就可以调用

9

判断对象中是否有某个属性
使用in操作符

let obj = {
    name: undefined,
};
console.log("name" in obj); // true

10

对象遍历输出顺序
整数属性会被排序而其余属性按照创建的顺序
整数属性指的是一个可以在不做任何更改的情况下与一个整数进行相互转换的字符串

String(Math.trunc(+"20")) // "20" 相同所以是整数属性
String(Math.trunc(+"+20")) // "20" 不同所以不是整数属性

11

对象的克隆合并
第一个参数是目标对象
从第二个开始的参数是源对象
该方法将从第二个开始的参数的所有属性拷贝到第一个参数并返回目标对象
该方法对于目标对象已经存在的属性会进行覆盖

let obj = {
    name: "wqd",
};
let a = {
    name: "wang",
};
let b = {
    age: 25,
};
Object.assign(obj, a, b);
console.log(obj); // {name: "wang", age: 25}

对象的简单克隆

let obj = {
    name: "wqd",
};
let a = Object.assign({}, obj);
console.log(a); // {name: "wqd"}

12

构造函数

function User() {
    // 隐式创建
    // let this = {};
    this.name = "wqd";
    this.age = 25;
    // 隐式返回
    // return this;
}
let user = new User();
console.log(user); // {name: "wqd", age: 25}

如果return返回的是一个对象则构造函数返回该对象否则返回this

function User() {
    this.name = "wqd";
    return {
        name: "wang",
    };
}
console.log(new User().name); // "wang"

13

可选链
如果可选链前面的部分是null或者undefined则会停止运算并返回该部分而不报错

let user = {};
console.log(user?.address?.street); // undefined

14

对象的属性键只能是字符串类型或者Symbol类型
Symbol允许我们创建对象的隐藏属性并且会在循环中跳过
但是对象的克隆和合并会同时复制字符串Symbol属性

let id = Symbol("id"); // 即使描述一样也是不同的Symbol
let user = {
    name: "wqd",
    [id]: 25, // Symbol作为属性键需要用方括号包起来
};
for (let i in user) {
    console.log(i); // "name"
}
console.log(user[id]); // 25
console.log(Object.keys(user)); // ["name"] 同样会忽略Symbol

15

如何让相同名字的Symbol具有相同的实体
注册表内的Symbol被称为全局Symbol

let id1 = Symbol.for("id"); // 从全局注册表中读取不存在则创建
let id2 = Symbol.for("id");
console.log(id1 === id2); // true
console.log(Symbol.keyFor(id1)); // "id" 反向调用通过Symbol返回名字

16

对象到原始值的转换
分为string number default三种hint

let user = {
    name: "wqd",
    age: 25,
    [Symbol.toPrimitive](hint) {
        console.log(hint);
        switch(hint) {
            case "string":
                return this.name;
            case "number":
                return this.age;
            case "default":
                return this.age;
        }
    },
};
console.log(String(user)); // "string" "wqd"
console.log(+user); // "number" 25
console.log(user + 25); // "default" 50

17

一种特殊的内建比较方法
类似于严格相等但是对于两种边缘情况更可靠

Object.is(NaN, NaN) // true
Object.is(+0, -0) // false

18

创建数组的副本

let arr = [1, 2, 3];
let copy = arr.slice();
arr.pop();
console.log(arr); // [1, 2]
console.log(copy); // [1, 2, 3]

19

数组方法之reducereduceRight
应用函数时上一个函数调用的结果将作为第一个参数传递给下一个函数

let arr = [1, 2, 3, 4, 5];
let result = arr.reduce((previous, current) => previous + current, 0);
console.log(result); // 15

20

判断是否是数组

typeof [] // "object" 这是错误的因为数组没有单独的类型
Array.isArray([]) // true 使用特定语法去判断

21

可迭代对象
可以应用for of循环的对象称为可迭代的

let range = {
    from: 1,
    to: 5,
};
range[Symbol.iterator] = function() {
    return {
        min: this.from,
        max: this.to,
        next() {
            if (this.min > this.max) {
                return {
                    done: true,
                };
            } else {
                return {
                    done: false,
                    value: this.min++,
                };
            }
        },
    };
}
for (let i of range) {
    console.log(i); // 1 2 3 4 5
}

22

可迭代类数组的值中获取数组

let wqd = {
    0: "a",
    1: "b",
    length: 2,
};
let a = Array.from(wqd, item => item + item);
console.log(a); // ["aa", "bb"]

23

映射
和对象最大的区别是Map允许任何类型的键

let map = new Map(); // 创建
map.set("123", "string"); // 根据键存储值
map.set(123, "number");
console.log(map.get(123)); // "number"
console.log(map.get(456)); // undefined
console.log(map.has("123")); // true
console.log(map.has(456)); // false

Map迭代
迭代的顺序与插入值的顺序相同

map.keys() // 遍历所有的键
map.values() // 遍历所有的值
map.entries() // 遍历所有的实体

从对象创建Map

let obj = {
    name: "wqd",
    age: 25,
};
let map = new Map(Object.entries(obj));
console.log(map.get("age")); // 25

Map创建对象

let obj = Object.fromEntries([
    ["a", 1],
    ["b", 2],
    ["c", 3],
]);
console.log(obj.a); // 1

24

集合
其中的每个值只能出现一次

let set = new Set();
let a = {
    name: "a",
};
let b = {
    name: "b",
};
let c = {
    name: "c",
};
set.add(a);
set.add(b);
set.add(c);
set.add(a);
set.add(b);
set.add(c);
console.log(set.size); // 3 set只保留不重复的值

25

弱映射
WeakMapMap的第一个不同点是WeakMap的键必须是对象
WeakMapMap的第二个不同点是如果我们在WeakMap中使用一个对象作为键并且没有对这个对象的引用那么这个对象会被从内存中自动清除

26

弱集合
WeakMapWeakSet最明显的局限性就是不能迭代并且无法获取当前所有内容

27

转换对象

let obj = {
    a: 1,
    b: 2,
    c: 3,
};
let double = Object.fromEntries(Object.entries(obj).map(
    ([key, value]) => [key, value * 2]
));
console.log(double); // {a: 2, b: 4, c: 6}

28

解构赋值

let arr = ["aa", "bb", "cc"];
let [a, b, c] = arr; // 数组解构
console.log(a, b, c); // 1 2 3

交换变量值的技巧

let a = 123;
let b = 456;
[a, b] = [b, a];
console.log(a, b); // 456 123

剩余的

let [a, b, ...rest] = [1, 2, 3, 4];
console.log(rest); // [3, 4]

29

Rest参数

function wqd(a, b, ...rest) {
    console.log(a + b); // 3
    console.log(rest); // [3, 4, 5]
}
wqd(1, 2, 3, 4, 5);

30

Spread语法
任何可迭代对象都可以使用

let a = [1, 2];
let b = [5, 6];
let c = [...a, 3, 4, ...b];
console.log(c); // [1, 2, 3, 4, 5, 6]

31

使用Spread语法获取数组和对象的副本

let arr = [1, 2, 3];
let a = [...arr];
console.log(JSON.stringify(arr) === JSON.stringify(a)); // true
console.log(arr === a); // false
let obj = {
    a: 1,
    b: 2,
    c: 3,
};
let b = {...obj};
console.log(JSON.stringify(obj) === JSON.stringify(b)); // true
console.log(obj === b); // false

32

闭包
内部函数总是可以访问其所在的外部函数中声明的变量和参数

33

var不是函数作用域就是全局作用域
声明会被提升但是赋值不会

function a() {
    a = false;
    if (false) {
        var a;
    }
    console.log(a); // false
}
a();
function b() {
    console.log(b); // undefined
    var b = false;
}
b();

34

嵌套的setTimeout能精确地设置两次执行之间的延时而setInterval不能
因为嵌套的setTimeout的下一次调用是在前一次调用完成时再进行的

let a = setTimeout(function f() {
    // todo
    a = setTimeout(f, 1000);
}, 1000);

35

call允许调用一个显式设置this的函数

function f() {
    console.log(this.name);
}
let a = {
    name: "a",
};
let b = {
    name: "b",
};
f.call(a); // "a"
f.call(b); // "b"

36

callapply之间唯一的语法区别是call期望一个参数列表apply期望一个类数组对象

37

防抖装饰器
debounce会在冷却期后运行函数一次适用于处理最终结果

function debounce(f, ms) {
    let timeout;
    return function() {
        clearTimeout(timeout);
        timeout = setTimeout(() => f.apply(this, arguments), ms);
    };
}

节流装饰器
throttle运行函数的频率不会大于所给定的时间适用于不应该经常进行的定期更新

38

call apply bind的区别
callapply本质相同但call一个一个传参apply数组传参
callbind完全相同但是bind不会立即调用函数而是返回一个新函数

39

属性标志和属性描述符
value
writable为false时只读
enumerable为false时不可枚举
configurable为false时不可配置

40

原生的原型

let obj = {};
console.log(obj.__proto__ === Object.prototype); // true

41

继承静态属性和方法

class A {}
class B extends A {}
// 对于静态的
console.log(B.__proto__ === A); // true
// 对于常规的
console.log(B.prototype.__proto__ === A.prototype); // true

有无extends的区别

class A {}
console.log(A.__proto__ === Function.prototype); // true
class A extends Object {}
console.log(A.__proto__ === Object); // true

42

受保护的属性和方法

class A {
    _count = 0; // 受保护的属性
    setCount(value) {
        if (value < 0) {
            return;
        }
        this._count = value;
    }
    getCount() {
        return this._count;
    }
    // 只设置get函数不设置set函数实现只读
    getName() {
        return this._name;
    }
    constructor(name) {
        this._name = name;
    }
}

43

类型检查方法

Object.prototype.toString.call(123) // "[object Number]"

44

Promise的5种静态方法

Promise.all
Promise.allSettled
Promise.race

45

generator

function* wqd() {
  let a = yield "2 + 2";
  console.log(a); // 4
  let b = yield "3 * 3";
}
let generator = wqd();
console.log(generator.next().value); // "2 + 2"
console.log(generator.next(4).value); // "3 * 3"

46

for infor of的区别
通过for in循环我们可以遍历一个对象自有的继承的可枚举的非Symbol的属性
通过for of我们可以迭代可迭代对象

47

构造函数相关

function Parent() {}
Parent.prototype.name = "a";
function Child() {}
Child.prototype = Object.create(Parent.prototype);
Child.prototype.constructor = Child;
let childOne = new Child();
console.log(childOne.name); // "a"
Child.prototype.name = "b";
let childTwo = new Child();
console.log(childTwo.name); // "b"

48

交换两个变量的值

let a = 0, b = 1;
let c = a;
a = b;
b = c;
console.log(a, b); // 1 0
let a = 0, b = 1;
a = a + b;
b = a - b;
a = a - b;
console.log(a, b); // 1 0
let a = 0, b = 1;
a = [a, b];
b = a[0];
a = a[1];
console.log(a, b); // 1 0
let a = 0, b = 1;
a = {a: b, b: a};
b = a.b;
a = a.a;
console.log(a, b); // 1 0
let a = 0, b = 1;
a = [b, b = a][0];
console.log(a, b); // 1 0
let a = 0, b = 1;
a = a ^ b;
b = a ^ b;
a = a ^ b
console.log(a, b); // 1 0
let a = 0, b = 1;
[a, b] = [b, a];
console.log(a, b); // 1 0

49

获得当前滚动的值

window.pageYOffset
window.pageXOffset // 都是只读的

50

页面滚动的方法
window.scrollTo(x, y) 将页面滚动至绝对坐标
window.scrollBy(x, y) 相对当前位置移动坐标
element.scrollIntoView(boolean) 将element移动到窗口顶部或底部

51

清除浮动的方法
使用clear 创建一个空的块级元素放到末尾并设置clear
使用BFC 给父元素添加overflow或float
使用伪元素 原理同clear方法

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,752评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,100评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,244评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,099评论 1 286
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,210评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,307评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,346评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,133评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,546评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,849评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,019评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,702评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,331评论 3 319
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,030评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,260评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,871评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,898评论 2 351

推荐阅读更多精彩内容