Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

面试题 #10

Open
Wscats opened this issue Apr 10, 2017 · 0 comments
Open

面试题 #10

Wscats opened this issue Apr 10, 2017 · 0 comments

Comments

@Wscats
Copy link
Owner

Wscats commented Apr 10, 2017

写一段脚本,实现:当页面上任意一个链接被点击的时候,alert出这个链接在页面上的顺序号,如第一个链接则alert(1),依次类推。

var links = document.getElementsByTagName('a');
console.log(links);
for (var i = 0; i < links.length; i++) {
    links[i].onclick = (function (i) {
        return function () {
            alert(i)
        }
    })(i)
}
//or
var links = document.getElementsByTagName('a');
console.log(links);
for (let i = 0; i < links.length; i++) {
    links[i].onclick = function (i) {
        alert(i)
    }
}

创建”内置”方法:给String对象定义一个repeatify方法,该方法接收一个整数参数,作为字符串重复的次数,最后返回重复指定次数的字符串。

String.prototype.repeatify = function (num) {
    var str = "";
    for (var i = 0; i < num; i++) {
        str += this;
    }
    return str;
}
console.log("laoxie".repeatify(4))

完成一个函数,接受数组作为参数,数组元素为整数或者数组,数组元素包含整数或数组,函数返回扁平化后的数组,如:[1,[2,[[3,4],5],6]] = > [1,2,3,4,5,6]。

var arr = [1, [2, 3, [4, 5, [6]]], 7];
var newArr = [];

function getNewArr(arr) {
    for (var i = 0; i < arr.length; i++) {
        if (typeof arr[i] == "number") {
            newArr.push(arr[i])
        } else {
            getNewArr(arr[i])
        }
    }
}
getNewArr(arr)

假设现有一篇文章 var content = “…大量文字”,文章触及到一些敏感词[“wscat”,“yao”,“eno”,“6.1”]等,如何在文章中发现这些敏感词,并将背景置为红色或改变字体颜色标识出来。

var str = "6.1号,这是愉快的儿童节,我清晰地记得,愚蠢的yao牵着可爱的eno...";
var keyword = ["老谢", "老蓝", "千锋", "6.1"];
for (var i = 0; i < keyword.length; i++) {
    str = str.split(keyword[i]);
    str = str.join("<span style='color:red'>" + keyword[i] + "</span>")
    console.log(str)
}
document.getElementById('str').innerHTML = str;

不能使用定时器,实现5s刷新一次页面

定时自动刷新,content表示刷新间隔,单位为秒s,下面代码表示页面每隔三秒刷新一次

<meta http-equiv="refresh" content="3">

这种方法实现页面刷新有点投机取巧,这个标签作用是定时跳转,content第一个参数表示间隔时间,单位为秒,第二个参数表示目标网址,但是如果把第二个参数设为#,就会实现页面刷新

<meta http-equiv="refresh" content="3;url=#">

event.currentTarget和event.target的不同

可以发现,由于事件捕获和事件冒泡的存在,很多时候注册的事件监听者event.currentTarget并不是事件的触发者event.target,大部分时候事件可能是由子元素触发的,但是在捕获、冒泡的过程中被父级元素的事件监听器获取到了,注册监听事件的父级元素就是这种情况下event.currentTarget,而事件触发者也就是子元素就是event.target

<head>
	<meta charset="utf-8">
	<title>菜鸟教程(runoob.com)</title>
</head>
<body>
	<p>该实例使用 addEventListener() 方法在按钮中添加点击事件。 </p>
	<button id="myBtn">点我</button>
	<p id="demo"></p>
	<script>
		var btn = document.getElementById("myBtn");
		btn.addEventListener("click", function displayDate1(e) {
			console.log('按钮注册点击事件');
			console.log("e.currentTarget", e.currentTarget);
			console.log("e.target", e.target);
			console.log("this", this)
		});
		document.body.addEventListener("click", function displayDate1(e) {
			console.log('body注册点击事件');
			console.log("e.currentTarget", e.currentTarget);
			console.log("e.target", e.target);
			console.log("this", this)
		});
	</script>
</body>
</html>

css加载会阻塞DOM树渲染吗?

不会

  • css加载不会阻塞DOM树的解析
  • css加载会阻塞DOM树的渲染
  • css加载会阻塞后面js语句的执行

这可能也是浏览器的一种优化机制。因为你加载css的时候,可能会修改下面DOM节点的样式,如果css加载不阻塞DOM树渲染的话,那么当css加载完之后,DOM树可能又得重新重绘或者回流了,这就造成了一些没有必要的损耗。所以我干脆就先把DOM树的结构先解析完,把可以做的工作做完,然后等你css加载完之后,在根据最终的样式来渲染DOM树,这种做法性能方面确实会比较好一点,摘自css加载会造成阻塞吗?

defer和async的区别

<script src="script.js"></script>

没有 defer 或 async,浏览器会立即加载并执行指定的脚本,“立即”指的是在渲染该 script 标签之下的文档元素之前,也就是说不等待后续载入的文档元素,读到就加载并执行。

<script async src="script.js"></script>

有 async,加载和渲染后续文档元素的过程将和 script.js 的加载与执行并行进行(异步)。

<script defer src="myscript.js"></script>

有 defer,加载后续文档元素的过程将和 script.js 的加载并行进行(异步),但是 script.js 的执行要在所有元素解析完成之后,DOMContentLoaded 事件触发之前完成。defer和async的区别

image

遍历一个某一元素下的所有子元素(包括子元素的子元素)的方法,打印出所有子元素的ID

假设要遍历document.body

var allNodes = [];
function getChildNode(node) {
    //先找到子结点
    var nodeList = node.childNodes;
    for (var i = 0; i < nodeList.length; i++) {
        //childNode获取到到的节点包含了各种类型的节点
        //但是我们只需要元素节点  通过nodeType去判断当前的这个节点是不是元素节点
        var childNode = nodeList[i];
        //判断是否是元素结点
        if (childNode.nodeType == 1) {
            console.log(childNode.id);
            allNodes.push[childNode];
            //childNode.style.border = "1px solid red";
            getChildNode(childNode);
        }
    }
}
getChildNode(document.body);
//getChildNode("某元素");

f(1)=1, f(1)(2)=2, f(1)(2)(3)=6, 设置一个函数输出一下的值

难点:打印和相加计算,会分别调用toStringvalueOf函数,所以我们重写temp的toStringvalueOf方法,返回a的值,这里测试的时候发现只要改写toString就可以了

function add(a) {
    var temp = function (b) {
        return add(a + b);
    }
    temp.valueOf = temp.toString = function () {
        return a;
    };
    return temp;
}
console.log(add(1)(2));
alert(add(1)(2)(3));

简单讲,在对对象(广义的,包括函数对象)进行+ - * / == > < >= <=运算时,会依次尝试调用私有toString私有valueOf原型toString原型valueOf,直到遇到返回基本类型(如数字或字符串)停止,这里可以参考实现语法的功能:var a = add(1)(2)(3); //6没看懂别人的代码

var temp = function () {
    var a = 1 + 2;//这里执行了加法所以会执行temp.toString方法
    return temp;
};
temp.toString = function () {
    return "wscats";
};
console.log(temp());

从图片可以看出来,当改写了toString后,既返回了函数,还打印出了结果
2018-11-21 3 36 34

实现下面的函数new Test("test").firstSleep(3).sleep(5).eat("dinner")

具体可以参考链式调用

function Test(name) {
    this.task = [];
    let fn = () => {
        console.log(name);
        this.next();
    }
    this.task.push(fn);
    setTimeout(() => {
        this.next();
    }, 0)
    return this;
}

Test.prototype.firstSleep = function (timer) {
    console.time("firstSleep")
    let that = this;
    let fn = () => {
        setTimeout(() => {
            console.timeEnd("firstSleep");
            that.next();
        }, timer * 1000)
    }
    this.task.unshift(fn);
    return this;
}

Test.prototype.sleep = function (timer) {
    console.time("sleep")
    let that = this;
    let fn = () => {
        setTimeout(() => {
            console.timeEnd("sleep");
            that.next();
        }, timer * 1000)
    }
    this.task.push(fn);
    return this;
}

Test.prototype.eat = function (dinner) {
    let that = this;
    let fn = () => {
        console.log(dinner);
        that.next();
    }
    this.task.push(fn);
    return this;
}

Test.prototype.next = function (dinner) {
    let fn = this.task.shift();
    fn && fn()
}

new Test("test").firstSleep(3).sleep(5).eat("dinner")

如何优化if...else语句

决策树和卫语句

const a = 3;  
//bad:
if (a === 1) {
    console.log('a > 1');
}
if (a === 2) {
    console.log('a > 2');
}
if (a === 3) {
    console.log('a > 3');
}
if (a === 4) {
    console.log('a > 4');
}
// good:
switch(a) {
    case 1:
        console.log('a = 1');
    case 2:
        console.log('a = 2');
    case 3:
        console.log('a = 3');
    defaut:
        console.log('blablabla');
}
const judgeMap = {
    1: () => { console.log('a = 1') },
    2: () => { console.log('a = 2') },
    3: () => { console.log('a = 3') },
    4: () => { console.log('a = 4') }
}
judgeMap[a]();

三元表达式

const strength = (password.length > 7) ? 'Strong' : 'Weak';

position:sticky

不用JS情况写滑动到头部固定,参考杀了个回马枪,还是说说position:sticky吧

交换变量

let a;
let b;

[a, b] = [1, 2, 3];

https://dmitripavlutin.com/swap-variables-javascript/

以下表达式 (a== 1 && a ==2 && a==3)可以为真吗?

  • 如果a是一个对象Object,那在执行a==的时候首先会去先执行valueOf方法,如果没有valueOf方法,就会去执行toString方法。(toString方法与valueOf类似,这里不再重复)
const a = { value: 0 }
a.valueOf = function () {
    return  this.value += 1
}
console.log( a == 1 && a == 2 && a == 3 );
  • 如果a是一个数组Array,在数组转换成字符串的时候,数组toString会隐含调用join()方法
const a = [1, 2, 3];
a.join = a.shift;
console.log( a == 1 && a == 2 && a ==3 );
  • 扩展:字符编码实现相同效果
var aᅠ = 1;
var a = 2;
var ᅠa = 3;
console.log(aᅠ === 1 && a === 2 && ᅠa=== 3 );

变量提升

{
    a = 1;
    function a() { };
    a = 2;
    console.log(a); // 2
}
console.log(a); // 1

但是比上面会复杂一点,因为还涉及到块作用域,因为函数写在块作用域里面,由于函数提升,它即能访问局部作用域,也能访问全局作用域,所以此时会在全局作用域和块级作用域都产生一个变量 a

JavaScript 执行到函数所在的那一句把局部变量的内容扔给外面的那个变量

即相当如下的代码:

let outera;
{

    let innera;
    innera = function () { };
    innera = 1;
    // function a() { };
    outera = innera; // JavaScript 执行到函数所在的那一句把局部变量的内容扔给外面的那个变量
    innera = 2;
    console.log(innera); // 2
}
console.log(outera); // 1
@Wscats Wscats changed the title 几道面试题 面试题 Jan 23, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant