赞
踩
目录
3、new的原理是什么? 通过字面量和new创建对象的区别?
5、Promise的特征是什么? Promise构造函数执行和then函数执行的区别?
对于call,apply的理解:
1、call 方法第一个参数是要绑定给this的值,后面传入的是一个参数列表。当第一个参数为null、undefined的时候,默认指向window。
2、apply接受两个参数,第一个参数是要绑定给this的值,第二个参数是一个参数数组。当第一个参数为null、undefined的时候,默认指向window。
3、bind 第一个参数是this的指向,从第二个参数开始是接收的参数列表。区别在于bind方法返回值是函数以及bind接收的参数列表的使用。
4、bind返回对应函数, 便于稍后调用; apply, call则是立即调用。
- /**
- * 实现思路:
- * 1. 当不传入第一个参数时,则默认上下文环境为window
- * 2. 改变this 指向,让新的对象可以执行该函数,并能接受参数
- *
- */
- Function.prototype.myCall=function(context){
- //如果调用者不是函数则抛出异常
- if(typeof this!=='function'){
- throw new TypeError('Error');
- }
- //如果context,没有传,或者传入undefined null 则this 执行 window
- context=context || window;
- context.fn=this;
- const args=[...arguments].slice(1);
- const result=context.fn(...args);
- delete context.fn;
- return result;
- }

- /**
- * apply实现思路与call相同,只是参数处理方式不同
- */
- Function.prototype.myApply=function(context){
- if(typeof this !=='function'){
- throw new TypeError('Error');
- }
- context=context||window;
- context.fn=this;
- let result=null;
- //如果传入参数则出入
- if(arguments[1]){
- result=context.fn(...arguments[1]);
- }else{
- result=context.fn();
- }
- //释放内存空间
- delete context.fn;
- return result;
- }

- /**
- * 实现思路如下:
- * 1. 对传入context的处理,如果不传或传null、undefined 则赋值为window
- * 2. 对于返回函数调用形式处理:
- * 2.1 普通函数调用
- * 对于该形式我们应该处理 f.bind(obj,2)(4)形式参数的处理
- * 2.2 new的方式调用
- * 对于该形式来说,this不会被外界传入改变
- */
- Function.prototype.myBind=function(context){
- if(typeof this !=='function'){
- throw new TypeError('error');
- }
- const that=this;
- const args=[...arguments].slice(1);
- context=context||window;
- return function F(){
- if(this instanceof F){
- return new that(...args,...arguments);
- }
- return that.apply(context,args.concat(...arguments));
- }
- }

JS浮点数计算精度问题是因为某些小数没法用二进制精确表示出来。JS使用的是IEEE 754双精度浮点规则。
- /**
- * 因为 0.1 和0.2 在表示小数时是无限循的
- * IEEE 754双精度版本(64)位就将超出部分进行裁剪
- * 所以就会出现下面的情况
- */
- //true
- 0.100000000000000002===0.1
- // true
- 0.200000000000000002 === 0.2
-
-
- parseFloat((0.1 + 0.2).toFixed(10)) === 0.3 // true
修正方案:
- function create(){
- //设置一个空对象
- let obj={};
- //取出构造函数
- var Cons=[].shift.call(arguments);
- //让空对象继承构造函数的prototype
- obj.__proto__=Cons.prototype;
- //执行构造函数
- let result=Cons.apply(obj,arguments);
- //确保返回的是一个对象
- return result instanceof Object?result:obj;
- }
-
- //测试如下:
- create(Person,'cc');
-
- function Person(name){
- this.name=name;
- console.log(name);
- }

2. 如果通过字面量创建对象,不需要通过作用域链一层层找到Object.
instanceof 可以检测某个对象是不是另一个对象的实例。
- /**
- *用来判断 用来判断 left对象是不是right对象的实例
- */
- function _instanceof(left,right){
- let prototype=right.prototype;
- left=left.__proto__;
- while(true){
- if(left===null || left===undefined){
- return false;
- }
- if(prototype===left){
- return true;
- }else{
- left=left.__proto__;
- }
- }
- }

原型继承的原理图:
该图应该注意以下几点:
1. 一切函数都是由 Function函数所创造
2. 一切函数的原型都指向Object, Object原型的原型指向 null
**:instanceof 操作符用来比较两个操作数的构造函数。只有在比较自定义的对象时才有意义
Promise特征:
Promise通过链式调用的方式解决回调嵌套问题,使我们代码更容易理解和维护;Promise 有三种状态 pending,resolved,rejected 这个承诺状态一旦从等待状态变成了其它状态就不能更改状态
Promise构造函数内的代码会立即
- console.log('外层执行环境');
-
- let p=new Promise((resolve,reject)=>{
- console.log('promise 执行');
- resolve('1');
- console.log('resolve 后面的语句');
- });
- p.then(resolveA)
- .then((res)=>console.log(res));
-
- function resolveA (value){
- return value+' success';
- }
-
- /**
- *
- * 外层执行环境
- * promise 执行
- * resolve 后面的语句
- * 1 success
- */

- const PENDING='pending';
- const RESOLVED='resolved';
- const REJECTED='rejected';
- function MyPromise(fn){
- //绑定this 让 下面函数中回调不丢失
- const that=this;
- that.state=PENDING;
- that.value=null;
- that.resolvedCallBacks=[];
- that.rejectedCallBacks=[];
- function resolve(value){
- if(that.state===PENDING){
- that.state=RESOLVED;
- that.value=value;
- //执行 then中的方法
- that.resolvedCallBacks.map(call=>call(that.value))
- }
- }
- function reject(value){
- if(that.state===PENDING){
- that.state=REJECTED;
- that.value=value;
- that.rejectedCallBacks.map(call=>call(that.value))
- }
- }
- //执行promise 中的函数
- try {
- console.log('new Promise');
- fn(resolve,reject);
- } catch (error) {
- reject(error);
- }
- }
- MyPromise.prototype.then=function(onFulfilled,onRejected){
- console.log('执行 then方法');
- const that=this;
- onFulfilled=typeof onFulfilled==='function'?onFulfilled:f=>f;
- onRejected=typeof onRejected==='function'?onRejected:error=>{throw error}
- if(that.state===PENDING){
- console.log('将 then中方法放到 数组中');
- that.resolvedCallBacks.push(onFulfilled);
- that.rejectedCallBacks.push(onRejected);
- }
-
- //将then中的方法放到数组中
- if(that.state===RESOLVED){
- onFulfilled(that.value);
- }
- if(that.state===REJECTED){
- onRejected(that.value);
- }
- }
-
- /**
- * 测试如下:
- */
-
- console.log('外层执行环境');
- let p=new MyPromise((resolve,reject)=>{
- console.log('promise 回调函数执行');
- setTimeout(()=>{resolve('1')},0);
- console.log('resolve 后面的语句');
- });
- p.then((res)=>{console.log(res+' success')});
-
-
- //测试结果
- /**
- 外层执行环境
- new Promise
- promise 回调函数执行
- resolve 后面的语句
- 执行 then方法
- 将 then中方法放到 数组中
- 1 success
- */

**: 可以通过我打印的日志把函数的执行顺序走一步.
async函数是Generator函数的语法糖,在函数内部使用 await来表示异步。
- /**
- * async 函数返回一个Promise对象
- * 函数内部 return 返回的值,会成为then方法回调的参数
- * 函数内部异常,会被 catch方法接收到。
- */
- async function test(){
- return '1';
- }
- async function test1(){
- throw new Error('error');
- }
-
- test()
- .then(v=>console.log(v))
- .catch(e=>console.log(e));
-
- test1()
- .then(v=>console.log(v))
- .catch(e=>console.log(e));

- /**
- *
- * 当 await 返回的是Promise对象时,
- * 只有等到所有 await中 promise执行完后,才执行then回调
- */
- const delay=t=>new Promise(resolve=>setTimeout(resolve,t));
- async function f(){
- await delay(1000);
- await delay(2000);
- return 'done';
- }
- f().then(v=>console.log(v)); //3s 后执行打印
- console.log('我先被执行');
- /**
- * 当 await后跟的是有状态的Promise时,
- * 此时之后所有的await都不会被执行
- */
- let a;
- async function func() {
- await Promise.reject('error');
- a = await 1;
- }
-
- func()
- .then(v => console.log(v, '-----------', a))
- .catch(e => console.log(e));
- //输出 error,而 then方法不会被执行
- /**
- * 通过 try-catch 对异常捕获
- * 使得后面的 await被执行
- */
- async function funcTryCatch() {
- try {
- await Promise.reject('error');
-
- } catch (error) {
- console.log('error,from try-cath')
- }
- a = await 1;
- return a;
- }
-
- funcTryCatch()
- .then(v => console.log(v, '-----------', a))
- .catch(e => console.log(e));

V8实现了准确式GC,GC算法采用分代式垃圾回收机制。因此V8内存堆分为新生dui代和老生代两部分。
新生代算法
新生代中的对象一般存活时间较短,使用 Scavenge GC 算法。
在新生代空间中,内存空间分为两部分,分别为 From 空间和 To 空间。在这两个空间中,必定有一个空间是使用的,另一个空间是空闲的。新分配的对象会被放入 From 空间中,当 From 空间被占满时,新生代 GC 就会启动了。算法会检查 From 空间中存活的对象并复制到 To 空间中,如果有失活的对象就会销毁。当复制完成后将 From 空间和 To 空间互换,这样 GC 就结束了。
老生代算法
老生代中的对象一般存活时间较长且数量也多,使用了两个算法,分别是标记清除算法和标记压缩算法。
该文内容,会不断添加...
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。