个人网站可以收费吗,网络营销模式的有形收益包括,洛阳做网站公司汉狮价格,wordpress换主题了目录
原型
Function与Object
new fn()
原型链
constructor
function.length
默认参数:第一个具有默认值之前的参数个数
剩余参数#xff1a;不算进length
闭包
循环中
函数工厂#xff1a;形参传递
IIFE#xff1a;匿名闭包
let#xff1a;闭包
forEach()不算进length
闭包
循环中
函数工厂形参传递
IIFE匿名闭包
let闭包
forEach()和letfor类似
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
nn
缓存原值自增用缓存的原值进行运算
从左到右解析能组成符号就组 原型
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) // 124function 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() // 30function 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()//3constructor
f1,f2中本没有 constructor 但是会从构造函数的 prototype 中查找相当f1.prototype.constructorf2的原型被重新定义了指向基类 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属性undefined10NaN
f2.__proto__.aa() // NaN
f2.bb() // Uncaught TypeError: f2.bb is not a functionfunction.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 (n10)
f(20) // 31 (n11)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()和letfor类似
function setupHelp() {...helpText.forEach(function (text) {document.getElementById(text.id).onfocus function () {showHelp(text.help);};});
}setupHelp();setTimeout
var变量提升到全局可以重复声明
for(var i0;i2;i){setTimeout((){console.log(i)},1000)//3,3
}
for(var i0;i3;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.numn...}
obj.fn (function (num){this.num num * 3 // window.num20*3num // 21 return function(n){this.num n // 60 5 6520 10 30num // 21 1 2222 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, 30this this.count1
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 })()//bindObjJS预解析/编译变量提升 //虽然按顺序创建作用域不会报错a为声明
function foo() {console.log(a);
}function bar() {var abarfoo();
}bar(); //undefined
var awindow 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 //foo55是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] });优先级从右到左 优先级是从右到左的所以变量提升阶段 bundefined后将 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(delay0)setImmediate下个Event Loop执行
//宏任务队列[timer1]
//微任务队列[promise0]
setTimeout(() {console.log(timer1);Promise.resolve().then(function() {console.log(promise2);});Promise.resolve().then(function() {console.log(promise4);});
}, 0);
//宏任务队列[timer1timer2]
//微任务队列[promise0]
setTimeout(() {console.log(timer2);Promise.resolve().then(function() {console.log(promise3);});
}, 0);
//宏任务队列[timer1timer2]
//微任务队列[promise0promise1]
Promise.resolve().then(function() {console.log(promise1);
});
//执行start
console.log(start);
//执行当前所有微任务队列[promise0promise1]
//执行promise0时将promise5放入了微任务队列[promise1promise5]
//接着执行微任务队列输出promise1promise5
//当微任务队列为空开始执行宏任务队列[timer1timer2]队首的timer1
//执行timer1时碰到了微任务promise2放进微任务队列[promise2]
//宏任务timer1执行完了开始执行所有当前所有微任务[promise2]
//执行promise2完碰到微任务promise4放进微任务队列[promise4]
//当前微任务队列不为空接着执行promise4
//微任务队列为空接着执行宏任务队列队首[timer2]
//执行timer2时碰到了微任务promise3放进微任务队列[promise3]
//宏任务timer2执行完了开始执行所有当前所有微任务[promise3]// 打印结果 start promise0 promise1 promise5 timer1 promise2 promise4 timer2 promise3async、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 setTimeoutNode中的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中字符串是不可变的immutablestr是基本数据类型或者string对象String的方法都是返回新值
可变只有数组和对象不可变可以带来性能和安全性的好处 let strnew 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); // 输出 5nn
缓存原值自增用缓存的原值进行运算
从左到右解析能组成符号就组
编译器会从左到右一个字符一个字符解析如果已解析的字符已经能够组成一个符号再解析下一个字符判断下一个字符能否和已解析出的符号再次组合成一个符号如果能再不断重复如上过程如果不能则使用最终解析出的符号。 var n1
nn
console.log(n)//1//等价于
var n1;
//nn运算开始
var tempn; //编译器解析到“nn”中的“n”后会先在内存中缓存n的原值用来参与其他运算
n n1; //编译器解析到“nn”中的“”后会在做“”运算前将n自加
n temp; //变量自加结束后用缓存的原值进行“”运算
//nn运算结束
console.log(n) //1var a3,b;
ba*a;
console.log(b) //12var a3,b;
baa; //b(a)a, b34
console.log(b) //7 参考链接JS 经典面试题初篇(this, 闭包, 原型...)含答案 - 掘金