一道面试题
有一个构造函数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赋值
在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则会抛出异常。
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>
或者
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>
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>
区分数组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>