本文最后更新于 2025年7月30日 下午
枚举属性
操作符
自有属性
继承属性
可枚举属性
不可枚举属性
in 操作符
返回
返回
返回
返回
for/in 循环
返回
返回
返回
不返回
hasOwnProperty()
返回
不返回
返回
返回
propertyIsEnumerable()
返回
不返回
返回
不返回
Object.keys()
返回
不返回
返回
不返回
Object.getOwnPropertyNames()
返回
不返回
返回
返回
Reflect.ownKeys()
返回
不返回
返回
返回
虚拟 DOM 和 diff 算法 参考:https://juejin.cn/post/6994959998283907102 。
好处:
跨平台
只需要操作数据,开发效率更高
通过 DOM diff 算法,可减少不必要的 DOM 操作,提高性能
可迭代对象 可迭代对象是指实现了[Symbol.iterator]
方法属性的对象。注意,区分类数组对象。 类数组对象(伪数组对象)是指可以通过索引属性访问元素并且拥有一个 length
属性的对象。 可迭代对象和类数组对象并非是相互排斥的。比如,字符串既是可迭代对象又是类数组对象。
迭代器模式(特别是在 ECMAScript 这个语境下)描述了一个方案,即可以把有些结构称为“可迭代对象”(iterable),因为它们实现了正式的 Iterable 接口,而且可以通过迭代器 Iterator 消费。
可迭代对象是一种抽象的说法。基本上,可以把可迭代对象理解成数组或集合这样的集合类型的对象。它们包含的元素都是有限的,而且都具有无歧义的遍历顺序。不过,可迭代对象不一定都是集合对象,也可以是仅仅具有类似数组行为的其他数据结构。基本上,可以使用 for…of 循环的对象都是可迭代对象。
ES6 新语法 参考:https://juejin.cn/post/6854818580660387853 。https://juejin.cn/post/6844903581426925581 。
let、const
Set、Map、Symbol
for-of/for-in
模块导入导出
函数默认参数
箭头函数
类
展开运算符
对象的解构
字符串模版
箭头函数和普通函数
箭头函数没有没有原型对象。
箭头函数 this 值为其所在上下文的 this 值。
箭头函数箭头函数不能使用 arguments、super、new.target。
箭头函数不能定义生成器函数。
for-in 循环和 for-of 循环
for-in 循环:可用于遍历数组索引下标值和对象键名,大部分用于对象。
for-of 循环:可用于遍历可迭代对象(Array、String、Map、Set 等等),不能遍历类数组对象和对象。但是 for-of 循环和 Object.keys()、Object.vales()、Object.entries() 配合可用来遍历对象。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 const a = { sfd : 45 , eee : 93 };const b = ["sfd" , 45 , "eee" , 93 ];for (let s in a) { console .log(s); }for (let s in b) { console .log(s); }for (let s of a) { console .log(s); }for (let s of Object .keys(a)) { console .log(s); }
判断数据类型
Object.prototype.toString.call() 方法
typeof 操作符
instanceof 操作符
constructor 属性
此外,还有 Array.isArray(obj) 方法、isNaN(obj) 方法等可以精准判断。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 var und = undefined ;var nul = null ;var boo = true ;var num = 1 ;var str = "xys" ;var obj = new Object ();var arr = [1 , 2 , 3 ];var fun = function ( ) {};var date = new Date ();var reg = /a/g ;var err = new Error ();var arg; (function getArg ( ) { arg = arguments ; })();console .log(Object .prototype.toString.call(und)); console .log(Object .prototype.toString.call(nul)); console .log(Object .prototype.toString.call(boo)); console .log(Object .prototype.toString.call(num)); console .log(Object .prototype.toString.call(str)); console .log(Object .prototype.toString.call(obj)); console .log(Object .prototype.toString.call(arr)); console .log(Object .prototype.toString.call(fun)); console .log(Object .prototype.toString.call(date)); console .log(Object .prototype.toString.call(reg)); console .log(Object .prototype.toString.call(err)); console .log(Object .prototype.toString.call(arg)); console .log(typeof und); console .log(typeof nul); console .log(typeof boo); console .log(typeof num); console .log(typeof str); console .log(typeof obj); console .log(typeof arr); console .log(typeof fun); console .log(typeof date); console .log(typeof reg); console .log(typeof err); console .log(typeof arg); console .log(obj instanceof Object ); console .log(arr instanceof Array ); console .log(fun instanceof Function ); console .log(date instanceof Date ); console .log(reg instanceof RegExp ); console .log(err instanceof Error ); console .log(arg instanceof Arguments); obj.__proto__.constructor === Object ; arr.__proto__.constructor === Array ; fun.__proto__.constructor === Function ; date.__proto__.constructor === Date ; reg.__proto__.constructor === RegExp ; err.__proto__.constructor === Error ; arg.__proto__.constructor === Arguments;
说明:
Object.prototype.toString.call() 方法是最准确的方法。
typeof 操作符只用于原始值,对于 Null 类型其返回为 Object。
instanceof 操作符只用于引用值,且是假定只有一种全局环境,如果网页中包含多个框架多个全局环境,如果从一个框架向另一个框架传入一个数组,那么传入的数组与在第二个框架中原生创建的数组分别具有各自不同的构造函数。
constructor 属性只用于引用值,而且其可以被重写,所以不一定准确。
垃圾回收 JavaScript 是使用垃圾回收的语言,也就是说执行环境负责在代码执行时管理内存。在 C 和 C++ 等语言中,跟踪内存使用对开发者来说是个很大的负担,也是很多问题的来源。JavaScript 则为开发者卸下了这个负担,通过自动内存管理实现内存分配和闲置资源回收。
基本思路很简单:确定哪个变量不会再使用,然后释放它所占用的内存。这个过程是周期性的,即垃圾回收程序每隔一定时间(或者说在代码执行过程中某个预定的收集时间)就会自动运行。垃圾回收过程是个近似且不完美的方案,因为某块内存是否还有用,属于“不可判定的”问题,意味着靠算法是解决不了的。
以函数中局部变量的正常生命周期为例。函数中的局部变量会在函数执行时存在。此时,栈(或堆)内存会分配空间以保存相应的值。函数在内部使用了变量,然后退出。此时,就不再需要那个局部变量,它占用的内存可以释放,供后面使用。这种情况下显然不再需要局部变量了,但并不是所有时候都会这么明显。垃圾回收程序必须跟踪记录哪个变量还会使用以及哪个变量不会再使用,以便回收内存。如何标记未使用的变量也许有不同的实现方式。不过,在浏览器的发展史上,用到过两种主要的标记策略:标记清理和引用计数。
JavaScript 最常用的垃圾回收策略是标记清理(mark-and-sweep)。当变量进入上下文,如在函数内部声明一个变量时,这个变量会被加上存在于上下文中的标记。而在上下文中的变量,逻辑上讲,永远不应该释放它们的内存,因为只要上下文中的代码在运行,就有可能用到它们。当变量离开上下文时,也会被加上离开上下文的标记。给变量加标记的方式有很多种。比如,当变量进入上下文时,反转某一位;或者,可以维护“在上下文中”和“不在上下文中”两个变量列表,可以把变量从一个列表转移到另一个列表。标记过程中的实现并不重要,关键是策略。
垃圾回收程序运行的时候,会标记内存中存储的所有变量(标记方法有很多)。然后,它会将所有在上下文中的变量,以及被在上下文中的变量引用的变量的标记去掉。在此之后再被加上标记的变量就是待删除的,原因是任何在上下文中的变量都访问不到它们了。随后垃圾回收程序做一次内存清理,销毁带标记的所有值并收回它们的内存。
通过 const 和 let 声明提升性能。
隐藏类和删除操作。
event.target 和 event.currentTarget 在事件处理程序内部,this 对象始终等于 currentTarget 的值,target 只包含事件的实际目标。
如果事件处理程序直接添加在了意图的目标,则 this、currentTarget 和 target 的值是一样的。如果这个事件处理程序是添加到按钮的父节点(如 document.body)上,那么它们的值就不一样了。由于按钮本身并没有注册事件处理程序,因此 click 事件冒泡到 document.body,从而触发了在它上面注册的处理程序。
CommonJS 和 ES Module 参考:https://juejin.cn/post/6994224541312483336 。
CommonJS CommonJS 模块由 JS 运行时实现。 CommonJs 是单个值导出,本质上导出的就是 exports 属性。 CommonJS 是可以动态加载的,对每一个加载都存在缓存,可以有效的解决循环引用问题。 CommonJS 模块同步加载并执行模块文件
ES Module ES6 Module 静态的,不能放在块级作用域内,代码发生在编译时。 ES6 Module 的值是动态绑定的,可以通过导出方法修改,可以直接访问修改结果。 ES6 Module 可以导出多个属性和方法,可以单个导入导出,混合导入导出。 ES6 模块提前加载并执行模块文件, ES6 Module 导入模块在严格模式下。 ES6 Module 的特性可以很容易实现 Tree Shaking 和 Code Splitting。
输出判断题 1 2 3 4 5 6 7 8 9 10 11 12 13 14 function test1 (aaa, bbb ) { console .log(aaa, arguments [0 ], bbb, arguments [1 ]); aaa = 666 ; bbb = 777 ; console .log(aaa, arguments [0 ], bbb, arguments [1 ]); arguments [0 ] = 888 ; arguments [1 ] = 999 ; console .log(aaa, arguments [0 ], bbb, arguments [1 ]); } test1(111 , 222 );
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 function test1 (a, b ) { console .log(a, arguments [0 ], b, arguments [1 ]); a = "aaa" ; b = "bbb" ; console .log(a, arguments [0 ], b, arguments [1 ]); arguments [0 ] = "trueaaa" ; arguments [1 ] = "truebbb" ; console .log(a, arguments [0 ], b, arguments [1 ]); }function test2 (a = "aaabbb" , b ) { console .log(a, arguments [0 ], b, arguments [1 ]); a = "aaa" ; b = "bbb" ; console .log(a, arguments [0 ], b, arguments [1 ]); arguments [0 ] = "trueaaa" ; arguments [1 ] = "truebbb" ; console .log(a, arguments [0 ], b, arguments [1 ]); } test1(); test1("AAA" ); test2(); test2("AAA" );
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 function test1 (arg ) { console .log(arg); var arg = "hello1" ; function arg ( ) { console .log("aaa" ); } console .log(arg); }function test2 (arg ) { console .log(arg); var arg = "hello2" ; console .log(arg); } test1("hi1" ); test2("hi2" );
1 2 3 4 5 6 7 8 9 10 11 12 13 14 function type (t ) { return Object .prototype.toString.call(t).slice(8 , -1 ); }function fn1 (...args ) { return args; }function fn2 ( ) { return arguments ; }console .log(type(fn1(1 , 2 , 3 )));console .log(type(fn2(1 , 2 , 3 )));
1 2 3 4 5 6 7 8 9 10 11 12 13 console .log(a); a = 12 ;function fn ( ) { console .log(a); console .log(b); a = 13 ; var a = 14 ; let b = 15 ; console .log(a); } fn();console .log(a); console .log(b);
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 function showcase (value ) { switch (value) { case "A" : console .log("A" ); break ; case "B" : console .log("B" ); break ; case undefined : console .log(undefined ); break ; default : console .log("unKnown" ); } } showcase(new String ("A" ))[([4 , 2 , 1 ].reduce(Math .pow), ["" ].reduce(Math .pow))]; Symbol () === Symbol (); Symbol ("aa" ) === Symbol ("aa" );
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 Object .__proto__ === Function .__proto__; Object .__proto__ === Function .prototype; Array .__proto__ === Function .__proto__; Function .prototype === Function .__proto__; Function .prototype; Object .prototype.prototype; Object .prototype.__proto__; Function .prototype.prototype; "标准的7个汉字" .length; "11" == new String (11 ); "11" === new String (11 ); var s1 = "afa" ;var s2 = new String ("jodo" );Object .prototype.toString.call(s1); Object .prototype.toString.call(s2); s1 instanceof Object ; s2 instanceof Object ; console .log("Value is" + (s === "afa" ) ? "yes" : "no" );
其它问题