web前端之JavaScrip的笔试题


Promise笔试题-02

console.log(1);
// 宏仁务 2
setTimeout(_ => {
    
    
	console.log(2);
}, 1000);

async function fn() {
    
    
	console.log(3);
	// 宏仁务 3
	setTimeout(_ => {
    
    
		console.log(4);
	}, 20);
	
	// 结果为失败
	// 所以 微任务 1 
	// 报错永远不会执行
	return Promise.reject();
}

async function run() {
    
    
	console.log(5);
	await fn();
	// 微任务 1
	console.log(6);
}
run();

// 需要执行 150 MS 左右
for (let i = 0; i < 90000000; i++) {
    
    }

// 宏仁务 4
setTimeout(_ => {
    
    
	console.log(7);
	
	// 立即执行
	new Promise(resolve => {
    
    
		console.log(8);
		// 微任务 5
		resolve();
	}).then(_ => {
    
    
		console.log(9);
	})
}, 0);

console.log(10);

// 1
// 5
// 3
// 10
// Uncaught (in promise) undefined
// 7
// 8
// 9
// 4
// 2

prototype和__proto__的笔试题

function Fn() {
    
    
	// 代码字符串
	// 谁 new 就是谁的私有属性
	this.x = 100;
	this.y = 200;
	this.getX = function() {
    
    
		console.log(this.x);
	};
	// 每个函数都有 prototype 对象
	// 所以 prototype 是一个堆 Fn.prototype
	// Fn.prototype 对象也带 __proto__ 属性
	// 这个对象上有 constructor
	// constructor 指向函数本身
};

// 把 getX 挂载到 Fn 的原型对象上
// 生成一个新的堆内存
// 属于公共属性
Fn.prototype.getX = function() {
    
    
	console.log(this.x);
};

// 把 getY 挂载到 Fn 的原型对象上
// 生成一个新的堆内存
// 属于公共属性
Fn.prototype.getY = function() {
    
    
	console.log(this.y);
};

// 括号可加可不不加
// 都是创建类的实例
// 创建实例对象 f1 / f2 (堆)
// 同时创建 x: 100 y: 200  getX: function() { ... }
// 都是这个实例的私有属性
// 通过 this 创建的变量和对象都属于私有属性
// 实例都带 __proto__ 属性
// __proto__ 所属类的原型 prototype
// 通过原型链往上找都属于 实例(Fn.prototype) 的共有属性
let f1 = new Fn();
let f2 = new Fn;

 // Object内置类(堆)
// 有自己的 prototype 原型对象 
// prototype 指向 Object.prototype 原型对象
// 有自己的 __proto__ 属性
// 有自己的 constructor 属性
// constructor 指向 Object
// Object.prototype 的 __proto__ 指向的是 null

// 实例指向的堆内存不同,如果自己私有就不会往原型类上查找
// 因为这个 getX 函数自己私有
// 所以两个实例的 getX 方法不相等
console.log(f1.getX === f2.getX); // false

// 因为 getY 这个函数不是自己私有
// 所以往原型链上查找,结果相等
// 原因就是他们的 __proto__ 都指向 Fn.prototype 原型对象
console.log(f1.getY === f2.getY); // true

// 通过原型链查找到的是公共的 getY 
// 类似于 f1.getY === f2.getY
console.log(f1.__proto__.getY === Fn.prototype.getY); // true

// f1.__proto__.getX 找的是 Fn.prototype 公共属性
// f2.getX 因为自己私有
// 所以不相等
console.log(f1.__proto__.getX === f2.getX); // false

// f1.getX 属于自己私有的属性
// Fn.prototype.getX 本身就是公共属性
// 所以不相等
console.log(f1.getX === Fn.prototype.getX); // false

// f1 自己身上没有 constructor 
// 往原型对象上查找
// 又因为 constructor 指向 函数本身
// 所以结果就是 Fn 函数
console.log(f1.constructor); // Fn 函数

// Fn.prototype 的 __proto__ 指向的是 Object.prototy 
// 因为 Object.prototy 的 constructor 指向 Object 本身
// 所以是结果 Object
console.log(Fn.prototype.__proto__.constructor); // ƒ Object() { [native code] }

// f1.getX() 执行
// 并且 f1.getX 是属于自己私有
// 所以输出 100
// 函数执行前面有点
f1.getX(); // 100

// f1.__proto__.getX(); 
// 直接查找的是原型对象上的 getX()
// 原型上的是 console.log(this.x);
// 因为 f1.__proto__.getX(); getX() 前面有点
// 所以 相当于 f1.__proto__.x
// f1.__proto__.x 直接跳过自己(f1 实例对象(堆))往原型对象上查找
// 此时原型对象上也没有,再往 Object.prototype 对象上查找
// Object 对象上也没有
// 最后得到的是 undefined
f1.__proto__.getX(); // undefined

// 与 f1.getX(); 相同
f2.getY(); // 200
        
// Fn.prototype.getY(); 
// 直接查找的是原型对象上的 getY()
// 原型上的是 console.log(this.y);
// 因为 Fn.prototype.getY(); getY() 前面有点
// 所以 相当于 Fn.prototype.y
// Fn.prototype.y 直接跳过自己(f2 实例对象(堆))往原型对象上查找
// 此时原型对象上也没有,再往 Object.prototype 对象上查找
// Object 对象上也没有
// 最后得到的是 undefined
Fn.prototype.getY(); // undefined

JavaScript引用类型值值操和运算符优先级比较–笔试

let a = {
    
     n : 1 };
let b = a;
a.x = a = {
    
     n: 2 };    
// 如果改为这样
// a = a.x = { n: 2 }; 
// 结果还是一样
// JavaScript 中点(.)比 等号 (=) 的优先级高

console.log(a.x); // undefined
// a.x = a = { n: 2 }; 
// 这段代码可以写成这样子
// a.x = { n: 2 };
// a = { n: 2 };
// 因为 a 是引用类型数据。
// 所以当 a.x = { n: 2 };时引用值的地址改变;
// 此时全局的 let a = { n: 1, x: { n: 2 } };
// 接着又执行 a = { n: 2 };时 a 引用地址已经改变。
// 最后输出的结果就是 : undefined

console.log(b.x); // { n: 2 }
// 经过上面 a 的操作,
// 全局的 a 值已经变为 a = { n: 1, x: { n: 2 } };
// 而此时 b 引用的地址一直没有改变
// 所以输出结果为 { n: 2 }

原型与原型链–笔试-05

function A() {
    
    };

A.prototype.n = 1;
var b = new A(); // b 实例对象已经建立原型连接
// 原型对象指向被改变,不会切断 b 实例对象的的指向
A.prototype = {
    
    
    n: 2,
    m: 3
};
var c = new A(); // c 实例对象将根据新的原型建立连接
console.log(b.n, b.m); // 1 undefined 这里拿到是改变 prototype 之前的堆数据
console.log(c.n, c.m); // 2 3 这里拿到是改变 prototype 之后的堆数据
// 此题生成了两个堆内存
// 并且两个堆内存都有自己的实例存储 => b c

作用域-笔试

var a = 0, 
	b = 0;
	
function A(a) {
    
    
	// A(1)执行
	// 1.A函数被重置为
	// function A(b) {
    
    
		// console.log(a + b++);
	// };
	// 2.执行打印console.log(a++),
	// 因为此时的a是形参,形参的值是传入的1,
	// 所以打印1,而且形参a执行了++,此时值为2
	A = function (b) {
    
    
		// A(2)调用情况
		// 这个a采用的是闭包中的a,而不是全局中的a,
		// 所以是2,b是形参也是2,所以打印的是4
		// b使用的是传入的形参而不是全局中的b
		console.log(a + b++);
	};
	// 调用函数A(1)的时候执行这一行代码,
	// 并且把函数重置
	console.log(a++);
};
A(1); 
// 1
A(2); 
// 4

事件队列-笔试题

示例-1

setTimeout(() => {
    
    
	console.log(1);
}, 20);

console.log(2);

setTimeout(() => {
    
    
	console.log(3);
}, 10);

console.log(4);

// console.time('time');
for (let i = 0; i < 90000000; i++) {
    
    
	// 900000 5 个 0:2.57421875 ms 左右
	// 9000000 6 个 0:12.625 ms 左右
	// 90000000 7 个 0:116.13525390625 ms 左右
	// 900000000 8 个 0:525.622314453125 ms 左右
	// 9000000000 9 个 0:9807.490966796875 ms 左右
	// 90000000000 10 个 0:循环不出来了
}

// console.timeEnd('time');
console.log(5);

setTimeout(() => {
    
    
	console.log(6);
}, 8);

console.log(7);

setTimeout(() => {
    
    
	console.log(8);
}, 15);

console.log(9);
// 2 4 5 7 9   3 1 6 8

循环的时间都超过了所有定时器的时间,在宏仁务中,定时器会按照从上到下的顺序执行,不再按照设置的时间长短来执行。


示例-2

console.log(1);

setTimeout(()=>{
    
    
	console.log(2);
}, 50);

console.log(3);

setTimeout(()=>{
    
    
	console.log(4);
	while(1 === 1) {
    
    };
	// 遇到死循环,
	// 所有代码执行都是在主栈中执行,
	// 主栈永远结束不了,
	// 后面啥都不干
}, 0);

console.log(5);
// 1 3 5   4

示例-3

console.log(1);

// 宏仁务
setTimeout(function () {
    
    
	console.log(2);
}, 0);

// 微任务
Promise.resolve().then(function () {
    
    
		console.log(3);
	}).then(function () {
    
    
		console.log(4);
});

console.log(5);
// 1 5   3 4 2

JavaScript之变量提升-笔试题

1、自执行函数

var a = 10;
(function a() {
    
    
    console.log(a);
    a = 20;
    console.log(window.a);
    var a = 30;
    console.log(a);

    // 等同于
    // 内部作用域
    // var a; // 声明未赋值,结果为 undefined
    // console.log(a); // undefined
    // a = 20; // 内部作用域的a赋值为20
    // console.log(window.a); // window中a的值依然是10 
    // a = 30; // 内部作用域的a赋值为30
    // console.log(a); // 打印的是内部作用域中的a值为30
})();

2、变量提升与是否进入判断无关

var name = '张三';
function fn() {
    
    
    if (typeof name === 'undefined') {
    
    
        var name = '李四';
        // 变量提升与是否进入判断无关
        // 无论是否进入判断,变量都会提升
        // 所以typeof nema的结果为'undefined'
        console.log('辛苦了:' + name);
        // 辛苦了:李四
    } else {
    
    
        console.log('吃饭没:' + name);
    };
};
fn();

3、形参、未定义赋值

var a = 10,
    b = 20,
    c = 30;
function fn(a) {
    
    
    // 形参即是定义在函数中的变量
    a = 1;
    var b = 2;
    c = 3;
    // 给未定义的变量强行赋值,
    // 变量会挂载到全局
};
fn(100);

console.log(a, b, c);
// 10 20 3

4、in关键字、变量提升与判断无关

// ("a" in window) in 关键字查找window对象中是否存在变量a
// "a" in window成立了,所以这个条件不执行
if (!("a" in window)) {
    
    
    var a = 10;
};
console.log(a);
// undefined

5、形参、||表达式赋值

var fn = 'hello';
(function (fn) {
    
    
    // 定义形参即是定义了变量
    // 因为形参有对应的实参
    // 所以值为'hello'
    console.log(fn);
    // hello

    // 同一作用域内,可以使用var定义多个同名变量
    // 此处定义的fn变量会覆盖形参变量
    // 并且赋值为fn
    // ||前有值所以不往后执行
    // 所以赋值为'hello'
    var fn = fn || 'world';
    console.log(fn);
    // hello
})(fn);
console.log(fn);
// hello

6、函数提升的优先级高于一切

var n = 10;
function fn(n) {
    
    
    console.log(n);
    // ƒ n() { }
    var n = 20;
    console.log(n);
    // 20
    function n() {
    
     };
    console.log(n);
    // 20
};
fn(n);

console.log(n);
// 10

7、函数提升高于一切、重新赋值

function fn(fn) {
    
    
    console.log(fn);
    // ƒ fn() {
    
    
    //     console.log(fn);
    // }
    var fn = 20;
    console.log(fn);
    // 20
    function fn() {
    
    
        console.log(fn);
    };
};
fn(30);
var fn = 10;

console.log(fn);
// 10

8、总结

变量的提升是JavaScript的默认行为,它会将所有变量声明移动到当前作用域的顶部,并且可以在声明之前使用变量。初始化不会被提升(赋值留在原地),提升仅作用于变量的声明。


JavaScript之原型链–笔试题

1、基础示例

Professor.prototype.tSkill = 'JavaScript';
function Professor() {
    
    }
var professor = new Professor();

Teacher.prototype = professor;
function Teacher() {
    
    
	this.mSkill = 'html';
}
var teacher = new Teacher();

Student.prototype = teacher;
function Student() {
    
    
	this.pSkill = 'css';
}
var student = new Student();

console.log(student);
// Student {pSkill: 'css'}
console.log(student.tSkill);
// JavaScript
console.log(student.mSkill);
// html
console.log(student.pSkill);
// css

原型链的顶端是Object.prototype
Object.prototype下保存了toString()


2、笔试题——1

Professor.prototype.tSkill = 'JavaScript';
function Professor() {
    
    }
var professor = new Professor();

Teacher.prototype = professor;
function Teacher() {
    
    
this.mSkill = 'html';
this.success = {
    
    
alibaba: '28',
tencent: '30'
};
}
var teacher = new Teacher();

Student.prototype = teacher;
function Student() {
    
    
this.pSkill = 'css';
}
var student = new Student();

student.success.baidu = '100';
student.success.alibaba = '29';
console.log(teacher);
// Professor {mSkill: 'html', success: {… }}
// mSkill: "html"
// success: {alibaba: '29', tencent: '30', baidu: '100'}
// [[Prototype]]: Professor
console.log(student);
// Student {pSkill: 'css'}

猜你喜欢

转载自blog.csdn.net/weixin_51157081/article/details/122548715