new mediacontroller(this) this报错_你可能不知道的元属性new.target

c02631b841c28fca832722ffd11e3ca0.png

一道面试题

有一个构造函数Class,且不定义全局变量, 需满足如下条件:

 function Class(name){
      // 待实现
 }    

需满足:

const Class1 = new Class("张三");
const Class2 = new Class("李四");
Class1.id==1;                  // true
Class2.id==2;                  // true

console.log(Class1, Class2);
console.log(Class1.prototype == Class2.prototype);    // true

const Class3 = Class("王五");
Class3.id==3;                                         // true
console.log(Class3.prototype == Class2.prototype);    // true
console.log(Class3.prototype == Class1.prototype);    // true

instanceof 问题

在es5中,通常判断一个对象是否是一个类的实例的时候使用instanceof关键字,例如如下代码:

function Person(name) {
    if (this instanceof Person) {
        this.name = name
    } else {
        throw new Error('必须使用new关键字来调用Person')
    }
}

当判断this不是Person类的实例的时候,将会抛出一个异常。

但是如下通过call或apply修改this绑定作用域,那么** 在Person类中是无法区分到底是通过Person.call()或Person.apply()还是new关键字调用得到的Person实例 **。

所以,如下代码也能够正常执行:

let person = new Person('Leevare')
let anotherPerson = Person.call(person, 'Jason')   //this.name='Jason', 对person对象name赋值
74161b6b96ba4a50e9242a66fd565c72.png

在es6中引入了new.target这个元属性。当通过new的方式调用时,new.target将会被赋予新创建的对象实例,此处则为Person,其它方式将会为undefined。

function Person(name) {
    if(new.target !== Person) {
        throw new Error('必须使用new关键字来调用Person')
    }else {
        this.name = name
    }
}

此时,若使用call或apply则会抛出异常。

7bddf7f83cc113a59c8ed4bec8fbd2e0.png

new.target

使用场景: 如果一个构造函数不通过 new 命令生成实例, 就报错提醒或自身返回new 实例

ES6引入了new.target属性,用于确认当前作用的在哪个构造函数上。若没有通过new命令调用构造函数。则new.target会返回undefined,否则返回当前构造函数。

new.target语法由一个关键字"new",一个点,和一个属性名"target"组成。通常"new."的作用是提供属性访问的上下文,但这里"new."其实不是一个真正的对象。不过在构造方法调用中, new.target指向被new调用的构造函数,所以"new."成为了一个虚拟上下文 

new.target这个属性,当子类继承父类会返回子类的构造函数名称

class Parent {
        constructor() {
            //  Child子类继承父类, 那么父类构造函数中的 new.target 是子类构造函数的名称
            console.log(new.target)   
        }
    }
    
    class Child extends Parent {
        constructor() {
            super()
        }
    }
    
    // Child

new.target属性适用于所有函数访问的元属性。

html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Documenttitle>
head>

<body>
    <script>function Class(name) {if (new.target == Class) {this.name = name;this.id = ++Class.id;
            } else {return new Class(name);
            }
        }
        Class.id = 0;
        Class.prototype = {
            say() {
            }
        }const Class1 = new Class("张三");const Class2 = new Class("李四");console.log(Class1, Class2);console.log(Class1.prototype == Class2.prototype);const Class3 = Class("王五");console.log(Class3);console.log(Class3.prototype == Class2.prototype);console.log(Class3.prototype == Class1.prototype);script>
body>

html>
a4030016779996ab107c96a68d1b6e3b.png

或者

html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Documenttitle>
head>

<body>
    <script>function Class(name) {if (this instanceof Class) {this.name = name;this.id = ++Class.id;
            } else {return new Class(name);
            }
        }
        Class.id = 0;
        Class.prototype = {
            say() {
            }
        }const Class1 = new Class("张三");const Class2 = new Class("李四");console.log(Class1, Class2);console.log(Class1.prototype == Class2.prototype);const Class3 = Class("王五");console.log(Class3);console.log(Class3.prototype == Class2.prototype);console.log(Class3.prototype == Class1.prototype);script>
body>

html>
763611dc11c449af5e0ab038d2552ee9.png

Promise输出顺序面试题

html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Documenttitle>
    <script>const timeout = ms => new Promise((resolve, reject) => {
            setTimeout(() => {
                resolve();
            }, ms);
        });const ajax1 = () => timeout(5000).then(() => {console.log('1');return 1;
        });const ajax2 = () => timeout(1000).then(() => {console.log('2');return 2;
        });const ajax3 = () => timeout(2000).then(() => {console.log('3');return 3;
        });const mergePromise = ajaxArray => {// 在这里实现你的代码// 保存数组中的函数执行后的结果var data = [];// Promise.resolve方法调用时不带参数,直接返回一个resolved状态的 Promise 对象。var sequence = Promise.resolve();
            ajaxArray.forEach(function (item) {console.log(item);// 第一次的 then 方法用来执行数组中的每个函数,// 第二次的 then 方法接受数组中的函数执行后返回的结果,// 并把结果添加到 data 中,然后把 data 返回。
                sequence = sequence.then(item).then(function (res) {
                    data.push(res);return data;
                });
            })// 遍历结束后,返回一个 Promise,也就是 sequence, 他的 [[PromiseValue]] 值就是 data,// 而 data(保存数组中的函数执行后的结果) 也会作为参数,传入下次调用的 then 方法中。return sequence;
        };
        mergePromise([ajax1, ajax2, ajax3]).then(data => {console.log('done');console.log(data); // data 为 [1, 2, 3]
        });// 要求分别输出// 1// 2// 3// done// [1, 2, 3]script>
head>

<body>

body>

html>
html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Documenttitle>
    <script>const timeout = ms => new Promise((resolve, reject) => {
            setTimeout(() => {
                resolve();
            }, ms);
        });const ajax1 = () => timeout(5000).then(() => {console.log('1');return 1;
        });const ajax2 = () => timeout(1000).then(() => {console.log('2');return 2;
        });const ajax3 = () => timeout(2000).then(() => {console.log('3');return 3;
        });const mergePromise = async (urls) => {const arr = [];// 并发执行const textPromises = urls.map(url => {return url();
            });// 按次序输出for (const textPromise of textPromises) {
                arr.push(await textPromise);
            }return arr
        };
        mergePromise([ajax1, ajax2, ajax3]).then(data => {console.log('done');console.log(data); // data 为 [1, 2, 3]
        });// 要求分别输出// 1// 2// 3// done// [1, 2, 3]script>
head>

<body>

body>

html>

JS找出数组array出现最多的item项

不区分数组item类型

html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Documenttitle>
head>

<body>
    <script>var a = [1, 'a', 2, 3, 4, '4', 'c', 'aaa', 54, 54, 54, 54, 534, 43, 4, 56, 76, 8, 678, 78, 77, 97, 1, '54',1, "1", "a"];var b = a.reduce((obj, item) => {
            item in obj ? obj[item]++ : obj[item] = 1return obj
        }, {});var c = Object.entries(b).sort((a, b) => {return b[1] - a[1]
        });console.log(c);console.log(c[0]);script>
body>

html>
d1fd425d696e164076bac1395d9171b2.png

区分数组item类型

html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Documenttitle>
head>

<body>
    <script>var a = [1, 'a', 2, 3, 4, '4', 'c', 'aaa',54, 54, 54, 54, 534, 43, 4, 56, 76, 8,678, 78, 77, 97, 1, '54', 1, "1", "a"];var b = a.reduce((map, item) => {if (map.has(item)) {const val = map.get(item);
                map.set(item, val + 1);
            } else {
                map.set(item, 1);
            }return map;
        }, new Map());var c = [...b.entries()].sort((a, b) => {return b[1] - a[1]
        });console.log(c);console.log(c[0]);script>
body>

html>
1cfb31c4eb008ed3e0563f4bbff80cee.png
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值