js看代码说输出
目录
原型
Function与Object
new fn()
原型链
constructor
function.length
默认参数:第一个具有默认值之前的参数个数
剩余参数:不算进length
闭包
循环中
函数工厂:形参传递
IIFE:匿名闭包
let:闭包
forEach():和let+for类似
setTimeout
IIFE:匿名闭包
setTimeout(functionRef, delay, param...)
this+闭包
this
JS预解析/编译(变量提升)
let
暂时性死区
=优先级:从右到左
输出顺序Event loop
async、await事件轮询执行时机
async隐式返回Promise,会产生一个微任务await xx;后的代码在微任务时执行
Node中的process.nextTick
process.nextTick执行顺序早于微任务
string
str[i]=赋值
str.indexOf('',i):i
n=n++
缓存原值,自增,用缓存的原值进行运算
从左到右解析,能组成符号就组
原型
Function与Object
var F = function() {};Object.prototype.a = function() {console.log('a');
};Function.prototype.b = function() {console.log('b');
}var f = new F();f.a(); // a
f.b(); // f.b is not a functionF.a(); // a
F.b(); // b
new fn()
function A() {}
function B(a) {this.a = a;
}
function C(a) {if (a) {this.a = a;}
}
A.prototype.a = 1;
B.prototype.a = 1;
C.prototype.a = 1;console.log(new A().a); //1
console.log(new B().a); //undefined(传入a为undefined)
console.log(new C(2).a);//2
console.log(new C().a); //1
原型链
123['toString']:在数字 123 上使用方括号访问属性
数字本身没有toString
方法,则沿着__proto__
去function Number()
的prototype
上找,找到toString方法,toString方法的length是1
numObj.toString([radix])
console.log(123['toString'].length + 123) // 124
function fun(){this.a = 0this.b = function(){console.log("自己的b:",this.a)}
}fun.prototype = {b: function(){this.a = 20console.log("原型链b:",this.a)},c: function (){this.a = 30console.log(this.a)}
}var my_fun = new fun()my_fun.b() // 0
my_fun.c() // 30
function Foo() {getName = function (){console.log(1)}return this
}Foo.getName = function () {console.log(2)
}Foo.prototype.getName = function(){console.log(3)
}Foo.getName()//2Foo().getName();//1getName();//1:getName函数变量提升到全局new Foo.getName()//2 Foo函数有对象有个getName(...2)属性方法
//先对 new Foo() 实例化再对 A.getName() 调用,
//对 new Foo() 实例化调用的 getName() 方法是原型 prototype 上的
new Foo().getName()//3
// new new Foo().getName() => new B.getName(),
//先对 new Foo() 实例化再对 new B.getName() 实例化,
//new B.getName() 同时也在执行 B.getName() 方法输出的还是实例 B 上的方法也就是原型 prototype 的 getName
new new Foo().getName()//3
constructor
f1,f2中本没有 constructor
但是会从构造函数的 prototype
中查找相当f1.prototype.constructor
,f2
的原型被重新定义了指向基类 object
找不到的,只会往上找,而非往下,所以原型上不存在n
function Fn(){var n = 10this.m = 20this.aa = function() {console.log(this.m)}
}Fn.prototype.bb = function () {console.log("原型的this.n",this.n)
}var f1 = new FnFn.prototype = {aa: function(){console.log(this.m + 10)}
}var f2 = new Fn//注意区别修改原型Fn.prototype和修改原型的属性Fn.prototype.bb
console.log(f1.constructor) // ==> function Fn(){...}
console.log(f2.constructor) // ==> Object() { [native code] }//原型中
f1.bb() // n是 undefined
//自己有aa方法,就不去原型链上找了
f1.aa() // 20
f2.aa() // 20
//原型链上的aa方法中,原型没有m属性,undefined+10=NaN
f2.__proto__.aa() // NaN
f2.bb() // Uncaught TypeError: f2.bb is not a function
function.length
默认参数:第一个具有默认值之前的参数个数
function fn1 (name) {}function fn2 (name = '林三心') {}function fn3 (name, age = 22) {}function fn4 (name, age = 22, gender) {}function fn5(name = '林三心', age, gender) { }console.log(fn1.length) // 1
console.log(fn2.length) // 0
console.log(fn3.length) // 1
console.log(fn4.length) // 1
console.log(fn5.length) // 0
剩余参数:不算进length
function fn1(name, ...args) {}console.log(fn1.length) // 1
闭包
var ary = [1, 2, 3, 4]
function fn(i){return function(n){console.log(n+ (i++))}
}var f = fn(10)
f(20) // 30 (n+10)
f(20) // 31 (n+11)fn(20)(40) // 60
fn(30)(40) // 70// console.log(i) // Uncaught ReferenceError: i is not defined
循环中
变量 item
使用 var
进行声明,由于变量提升,所以具有函数作用域。当 onfocus
的回调执行时,item.help
的值被决定。由于循环在事件触发之前早已执行完毕,变量对象 item
(被三个闭包所共享)已经指向了 helpText
的最后一项。
function setupHelp() {...for (var i = 0; i < helpText.length; i++) {var item = helpText[i];document.getElementById(item.id).onfocus = function () {showHelp(item.help);};}
}setupHelp();
函数工厂:形参传递
function makeHelpCallback(help) {return function () {showHelp(help);};
}function setupHelp() {
...for (var i = 0; i < helpText.length; i++) {var item = helpText[i];document.getElementById(item.id).onfocus = makeHelpCallback(item.help);}
}setupHelp();
IIFE:匿名闭包
function setupHelp() {
...for (var i = 0; i < helpText.length; i++) {(function () {var item = helpText[i];document.getElementById(item.id).onfocus = function () {showHelp(item.help);};})(); // 马上把当前循环项的 item 与事件回调相关联起来}
}setupHelp();
let:闭包
function setupHelp() {
...for (let i = 0; i < helpText.length; i++) {const item = helpText[i];document.getElementById(item.id).onfocus = () => {showHelp(item.help);};}
}setupHelp();
forEach():和let+for类似
function setupHelp() {...helpText.forEach(function (text) {document.getElementById(text.id).onfocus = function () {showHelp(text.help);};});
}setupHelp();
setTimeout
var变量提升到全局,可以重复声明
for(var i=0;i<2;i++){setTimeout(()=>{console.log(i)},1000)//3,3
}
for(var i=0;i<3;i++){setTimeout(()=>{console.log(i)},1000)//3,3,3
}
console.log(i)//3
IIFE:匿名闭包
for (var i = 0; i < 5; i++) {(function(j) {setTimeout(function timer() {console.log(j);}, 1000);})(i);
}
//或者
for(var i = 0;i < 5;i++)
{setTimeout((function(i){return () => console.log(i);})(i),1000)
}
setTimeout(functionRef, delay, param...)
// 利用setTimeout的第三个参数,第三个参数将作为setTimeout第一个参数的参数
for (var i = 0; i < 5; i++) {setTimeout(function fn(i) {console.log(i);}, 1000, i); // 第三个参数i,将作为fn的参数
}
this+闭包
var num = 10 // 60; 65
var obj = {num: 20
}
//自执行obj.fn= function(n){this.num+=n...}
obj.fn = (function (num){this.num = num * 3 // window.num=20*3num++ // 21 return function(n){this.num += n // 60 + 5 = 65;20 + 10 =30num++ // 21 + 1 = 22;22 + 1 = 23 闭包引用numconsole.log(num)}
})(obj.num)var fn = obj.fn fn(5) // 22 this 指向 windowobj.fn(10) // 23 this 指向 objconsole.log(num, obj.num) // 65, 30
this
this.count=1
function func() {console.log(++this.count)//2
}func.count = 0
func()
obj = {func() {const arrowFunc = () => {console.log(this._name)}return arrowFunc},_name: "obj",
}obj.func()()//objfunc = obj.func
func()()//undefinedobj.func.bind({ _name: "newObj" })()()//newObjobj.func.bind()()()//undefinedobj.func.bind({ _name: "bindObj" }).apply({ _name: "applyObj" })()//bindObj
JS预解析/编译(变量提升)
//虽然按顺序创建作用域,不会报错a为声明
function foo() {console.log(a);
}function bar() {var a="bar"foo();
}bar(); //undefined
var a="window"
var a = 1;
function foo(a, b) {console.log(a); // 1a = 2;arguments[0] = 3;var a;console.log(a, this.a, b); // 3, 1, undefined
}
foo(a);
let
暂时性死区
function test() {var foo = 33;if (foo) {// var foo //foo+55是let 的 foolet foo = foo + 55; // ReferenceError}
}
test();
标识符 n.a 被解析为位于指令(let n)本身的 n 对象的属性 a。因为 n 的声明尚未执行结束,它仍然处于暂时性死区内
function go(n) {// n 在此处被定义console.log(n); // { a: [1, 2, 3] }for (let n of n.a) {// ^ ReferenceErrorconsole.log(n);}
}go({ a: [1, 2, 3] });
=优先级:从右到左
= 优先级是从右到左的,所以变量提升阶段 b=undefined后,将 c 赋值成 undefined
var b = {a,c: b
}
console.log(b.c);
//undefined
输出顺序Event loop
//宏任务队列:[]
//微任务队列:[promise0]
Promise.resolve().then(function() {console.log("promise0");}).then(function() {console.log("promise5");});
//定时的setTimeout(delay=0)=setImmediate:下个Event Loop执行
//宏任务队列:[timer1]
//微任务队列:[promise0]
setTimeout(() => {console.log("timer1");Promise.resolve().then(function() {console.log("promise2");});Promise.resolve().then(function() {console.log("promise4");});
}, 0);
//宏任务队列:[timer1,timer2]
//微任务队列:[promise0]
setTimeout(() => {console.log("timer2");Promise.resolve().then(function() {console.log("promise3");});
}, 0);
//宏任务队列:[timer1,timer2]
//微任务队列:[promise0,promise1]
Promise.resolve().then(function() {console.log("promise1");
});
//执行start
console.log("start");
//执行当前所有微任务队列:[promise0,promise1]
//执行promise0时将promise5放入了微任务队列:[promise1,promise5]
//接着执行微任务队列:输出promise1,promise5
//当微任务队列为空,开始执行宏任务队列[timer1,timer2]队首的timer1
//执行timer1时碰到了微任务promise2,放进微任务队列[promise2]
//宏任务timer1执行完了,开始执行所有当前所有微任务:[promise2]
//执行promise2完碰到微任务promise4,放进微任务队列:[promise4]
//当前微任务队列不为空,接着执行promise4
//微任务队列为空,接着执行宏任务队列队首[timer2]
//执行timer2时碰到了微任务promise3,放进微任务队列[promise3]
//宏任务timer2执行完了,开始执行所有当前所有微任务:[promise3]// 打印结果: start promise0 promise1 promise5 timer1 promise2 promise4 timer2 promise3
async、await事件轮询执行时机
async隐式返回Promise,会产生一个微任务
await xx;后的代码在微任务时执行
//1.script start(同步)
console.log("script start");async function async1() {await async2(); // await 隐式返回promiseconsole.log("async1 end"); // 这里的执行时机:在执行微任务时执行
}async function async2() {console.log("async2 end"); // 这里是同步代码
}
//2.async2 end(同步)
//微任务队列:[async1 end]
async1();
//宏任务队列:[setTimeout],setTimeOut进入下一loop
setTimeout(function() {console.log("setTimeout");
}, 0);
//3.Promise(同步)
//宏任务队列:[setTimeout]
//微任务队列:[async1 end,promise1]
new Promise(resolve => {console.log("Promise"); // 这里是同步代码resolve();
}).then(function() {console.log("promise1");}).then(function() {console.log("promise2");});
//4.script end(同步)
console.log("script end");
//当前loop的宏任务(都是同步代码)都执行完毕
//执行所有微任务[async1 end,promise1]
//执行promise1完后碰到了promise2,加入微任务队列,接着执行
//当前所有微任务都执行完毕,开始执行宏任务队列[setTimeout]// 打印结果: script start => async2 end => Promise => script end => async1 end => promise1 => promise2 => setTimeout
Node中的process.nextTick
process.nextTick执行顺序早于微任务
console.log("start");
//定时进入下一loop,宏任务队列:[timeout]
setTimeout(() => {console.log("timeout");
}, 0);
//微任务队列:[promise]
Promise.resolve().then(() => {console.log("promise");
});
//process.nextTick在微任务队首
//微任务队列:[nextTick,promise]
process.nextTick(() => {console.log("nextTick");Promise.resolve().then(() => {console.log("promise1");});
});
console.log("end");
// 执行结果 start end nextTick promise promise1 timeout
string
str[i]=赋值
在JavaScript中,字符串是不可变的(immutable),str是基本数据类型,或者string对象,String的方法都是返回新值
可变只有数组和对象,不可变可以带来性能和安全性的好处
let str=new String("123")
str[0]="z"
console.log(str[0])//1
str.indexOf('',i):i
let str = "Hello";
let index = str.indexOf("",0);
console.log(index); // 输出 0index = str.indexOf("",3);
console.log(index); // 输出 3index = str.indexOf("",6);
console.log(index); // 输出 5
n=n++
缓存原值,自增,用缓存的原值进行运算
从左到右解析,能组成符号就组
编译器会从左到右一个字符一个字符解析,如果已解析的字符已经能够组成一个符号,再解析下一个字符,判断下一个字符能否和已解析出的符号再次组合成一个符号,如果能,再不断重复如上过程;如果不能,则使用最终解析出的符号。
var n=1
n=n++
console.log(n)//1//等价于
var n=1;
//n=n++运算开始
var temp=n; //编译器解析到“n=n++”中的“n++”后,会先在内存中缓存n的原值,用来参与其他运算
n = n+1; //编译器解析到“n=n++”中的“=”后,会在做“=”运算前将n自加
n = temp; //变量自加结束后,用缓存的原值进行“=”运算
//n=n++运算结束
console.log(n) //1var a=3,b;
b=a++*a++;
console.log(b) //12var a=3,b;
b=a+++a; //b=(a++)+a, b=3+4
console.log(b) //7
参考链接:JS 经典面试题初篇(this, 闭包, 原型...)含答案 - 掘金
相关文章:
js看代码说输出
目录 原型 Function与Object new fn() 原型链 constructor function.length 默认参数:第一个具有默认值之前的参数个数 剩余参数:不算进length 闭包 循环中 函数工厂:形参传递 IIFE:匿名闭包 let:闭包 forEach()&am…...
Java笔记:使用javassist修改class文件内方法
1.前言 在工作突然有一个需求。线上运维的一个tomcat的web项目,运行的程序不正常。需要修改代码。可是这个项目代码非常的老,并且公司存储的源代码跟线上的不一致。 我了个擦,没有源代码但是还要结局客户的问题。只能到线上将对应程序的clas…...

华为云云耀云服务器L实例评测 |云服务器性能评测
通过上一篇文章华为云云耀云服务器 L 实例评测 |云服务器选购,我已经购买了一台 Centos 系统的云耀云服务器 L 实例。 在获得云耀云服务器 L 实例后,首要任务是熟悉云耀云服务器 L 实例的性能,对云耀云服务器 L 实例的性能进行测…...

iphone的safari浏览器实现全屏的pwa模式,并修改顶部状态栏背景颜色
要想修改顶部背景颜色,需要用到这个属性:content就是你要设置的颜色 <!-- 状态栏的背景色 --><meta name"theme-color" content"#f8f8f8" /> 然后再加上下面的设置: <!-- 网站开启对 web app 程序的支持…...

springboot对接rabbitmq并且实现动态创建队列和消费
背景 1、对接多个节点上的MQ(如master-MQ,slave-MQ),若读者需要自己模拟出两个MQ,可以部署多个VM然后参考 docker 安装rabbitmq_Steven-Russell的博客-CSDN博客 2、队列名称不是固定的,需要接受外部参数&…...

Spring的后处理器-BeanFactoryPostprocessor
目录 Spring后处理器 Bean工厂后处理器-BeanFactoryPostProcessor 修改beanDefinition对象 添加beanDefiniton对象 方法一 方法二 自定义Component Spring后处理器 Spring后处理器是Spring对外开放的重要拓展点(让我们可以用添加自己的逻辑)&…...

Flutter 必备知识点
Flutter 升级 确保在项目根目录下(含有 pubspec.yaml 的文件夹) 在命令行中输入命令: flutter channel输出: Flutter channels: * mastermainbetastable这个可以在 pubspec.yaml 中查看: 切换分支也很简单…...

什么是FMEA(失效模式和影响分析)?
失效模式和影响分析(FMEA)是一个在开发阶段,用于确定产品或流程可能的风险和失败点的有条理的过程。FMEA团队会研究失效模式,也就是产品或流程中可能出错的地方,以及这些失效可能带来的影响(如风险、损害、…...
Redis面试题(三)
文章目录 前言一、怎么理解 Redis 事务?二、Redis 事务相关的命令有哪几个?三、Redis key 的过期时间和永久有效分别怎么设置?四、Redis 如何做内存优化?五、Redis 回收进程如何工作的?六、 加锁机制总结 前言 怎么理…...
Python错误处理指南:优雅应对异常情况
目录 一. 异常是什么?二. 使用 try 和 except三. 捕获多个异常四. 使用 else五. 使用 finally六. 自定义异常七.Python中常见异常处理类型八.Python中常见异常处理实例九.异常处理最佳实践十.结论 当编写Python代码时,错误处理是一个重要的方面ÿ…...

MySQL学习笔记12
MySQL 查询语句: 1、查询五子句:(重点) mysql> select */字段列表 from 数据表名称 where 子句 group by 子句 having 子句 order by 子句 limit 子句; 1)where 子句;条件筛选。 2)group…...

【owt】构建m79的owt-client-native:使用vs2017
家里电脑换成了台式机,拷贝代码发现了三年前的owt客户端mfc工程。 不用下载第三方库,试着构建下: owt-client-native 我这里有3年前的代码,思索了下还是用vs2017构建吧: 重新构建一下 选用x86 的 vs2017 vs的命令行控制台 cls可以清理屏幕 之前构建过vs2022的webrtc原版 …...

Cpp/Qt-day020918Qt
目录 完善登录框 点击登录按钮后,判断账号(admin)和密码(123456)是否一致,如果匹配失败,则弹出错误对话框,文本内容“账号密码不匹配,是否重新登录”,给定两…...

Spring面试题10:Spring的XMLBeanFactory怎么使用
该文章专注于面试,面试只要回答关键点即可,不需要对框架有非常深入的回答,如果你想应付面试,是足够了,抓住关键点 面试官:Spring的XMLBeanFactory怎么使用 XmlBeanFactory是Spring框架中的一个实现类,它是BeanFactory接口的一个具体实现。XmlBeanFactory的主要作用是通…...

自定义数据类型
前言:小伙伴们又见面啦,今天这篇文章,我们来谈谈几种自定义数据类型。 目录 一.都有哪些自定义数据类型 二.结构体 结构体内存对齐 1.如何对齐 2.为什么要对齐 3.节省空间和提升效率的方法 (1)让占用空间小的成员…...
产品团队的需求验证和确认
需求核实过程是确保软件满足特定的规格要求,而验证则侧重于软件是否达到了最终用户的期望和需求。 如果你正在开发一种医疗产品,这种区别也可能在法规和标准中有所体现,例如: 820.30(f):设计验证应确认设计的成果符合…...

【JVM】类加载的过程
文章目录 类的生命周期加载验证准备解析初始化简要概括 类的生命周期 一个类型从被加载到虚拟机内存中开始,到卸载出内存为止,它的整个生命周期将会经历加载 (Loading)、验证(Verification)、准备…...
Golang 结构化日志包 log/slog 详解(四):分组、上下文和属性值类型
上一篇文章讲解了 log/slog 包中的自定义日志属性字段和日志级别,本文讲解下分组、上下文和属性值类型 分组输出 slog 支持将字段放在组中并且可以给分组指定名称。如何展示分组的内容,取决于使用的 handler,例如 TextHandler 使用点号分隔…...

小白学Python:提取Word中的所有图片,只需要1行代码
#python# 大家好,这里是程序员晚枫,全网同名。 最近在小破站账号:Python自动化办公社区更新一套课程:给小白的《50讲Python自动化办公》 在课程群里,看到学员自己开发了一个功能:从word里提取图片。这个…...
pip修改位于用户目录下的缓存目录
默认 pip 缓存目录: Windows: C:\Users\${用户名}\AppData\Local\pip\cache Linux: ~/.cache/pip 一、修改方式 1.命令方式 pip config set global.cache-dir "D:\kwok\data\pip-cache" 2.配置文件方式 ① Windows: C:\Users\${用…...

智慧工地云平台源码,基于微服务架构+Java+Spring Cloud +UniApp +MySql
智慧工地管理云平台系统,智慧工地全套源码,java版智慧工地源码,支持PC端、大屏端、移动端。 智慧工地聚焦建筑行业的市场需求,提供“平台网络终端”的整体解决方案,提供劳务管理、视频管理、智能监测、绿色施工、安全管…...
鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个医院挂号小程序
一、开发准备 环境搭建: 安装DevEco Studio 3.0或更高版本配置HarmonyOS SDK申请开发者账号 项目创建: File > New > Create Project > Application (选择"Empty Ability") 二、核心功能实现 1. 医院科室展示 /…...

(二)原型模式
原型的功能是将一个已经存在的对象作为源目标,其余对象都是通过这个源目标创建。发挥复制的作用就是原型模式的核心思想。 一、源型模式的定义 原型模式是指第二次创建对象可以通过复制已经存在的原型对象来实现,忽略对象创建过程中的其它细节。 📌 核心特点: 避免重复初…...

新能源汽车智慧充电桩管理方案:新能源充电桩散热问题及消防安全监管方案
随着新能源汽车的快速普及,充电桩作为核心配套设施,其安全性与可靠性备受关注。然而,在高温、高负荷运行环境下,充电桩的散热问题与消防安全隐患日益凸显,成为制约行业发展的关键瓶颈。 如何通过智慧化管理手段优化散…...

【开发技术】.Net使用FFmpeg视频特定帧上绘制内容
目录 一、目的 二、解决方案 2.1 什么是FFmpeg 2.2 FFmpeg主要功能 2.3 使用Xabe.FFmpeg调用FFmpeg功能 2.4 使用 FFmpeg 的 drawbox 滤镜来绘制 ROI 三、总结 一、目的 当前市场上有很多目标检测智能识别的相关算法,当前调用一个医疗行业的AI识别算法后返回…...

学习STC51单片机32(芯片为STC89C52RCRC)OLED显示屏2
每日一言 今天的每一份坚持,都是在为未来积攒底气。 案例:OLED显示一个A 这边观察到一个点,怎么雪花了就是都是乱七八糟的占满了屏幕。。 解释 : 如果代码里信号切换太快(比如 SDA 刚变,SCL 立刻变&#…...

ABAP设计模式之---“简单设计原则(Simple Design)”
“Simple Design”(简单设计)是软件开发中的一个重要理念,倡导以最简单的方式实现软件功能,以确保代码清晰易懂、易维护,并在项目需求变化时能够快速适应。 其核心目标是避免复杂和过度设计,遵循“让事情保…...

HarmonyOS运动开发:如何用mpchart绘制运动配速图表
##鸿蒙核心技术##运动开发##Sensor Service Kit(传感器服务)# 前言 在运动类应用中,运动数据的可视化是提升用户体验的重要环节。通过直观的图表展示运动过程中的关键数据,如配速、距离、卡路里消耗等,用户可以更清晰…...

Python基于历史模拟方法实现投资组合风险管理的VaR与ES模型项目实战
说明:这是一个机器学习实战项目(附带数据代码文档),如需数据代码文档可以直接到文章最后关注获取。 1.项目背景 在金融市场日益复杂和波动加剧的背景下,风险管理成为金融机构和个人投资者关注的核心议题之一。VaR&…...
Java数值运算常见陷阱与规避方法
整数除法中的舍入问题 问题现象 当开发者预期进行浮点除法却误用整数除法时,会出现小数部分被截断的情况。典型错误模式如下: void process(int value) {double half = value / 2; // 整数除法导致截断// 使用half变量 }此时...