不按期收集的面试题

Part1

1.判断数据类型的函数
function type_fn(a){
    let result;
    if(typeof a == 'object'){
    result = (a instanceof Array)?'Array':'object'
    }else{
    result = typeof a
    }
    return result
}

说明:鉴于 数组和对象和null的typeof都是object 因此基于typeof 另外须要instanceof判断区分

//补充 也能够用:Object.prototype.toString.call(a).slice(8,-1)
2.原型链继承的例子
function Class(){
    this.slogan = function(){
        console.log('我来自班级1');
    }
}

function Classmate(name){
    this.name = function(){
        console.log('我是'+name)
    }
}

Classmate.prototype = new Class();

//实例化
var peo1 = new Classmate('jerry');

peo1.name();    //我是jerry
peo1.slogan();  //我来自班级1
3.描述new一个对象的过程
建立一个新的对象
this指向新的对象
对this赋值 执行代码
返回this
4.zepto(或其余框架下如何使用原型链)
/**
 * 原型链继承的例子
 * 功能: 1.获取元素改变或者获取他的innerhtml。
 *       2.添加事件。
 */

//构造函数
function Elem(id){
    this.elem = document.getElementById(id);
};
//在其原型上添加方法
Elem.prototype.html = function(val){
    var elem=this.elem;
    if(val){
        elem.innerHTML = val;
        return this;  //链式调用
    }else{
        return elem.innerHTML;
    }
}

Elem.prototype.on = function(type,fn){
    var elem=this.elem;
    elem.addEventListener(type,fn);
    return this;
}


var div=new Elem('app');
div.html(`<h1>你好javascript</h1>`).on('click',function(){
    alert('我是天使')
})

原文连接:https://blog.csdn.net/qq_24675001/article/details/82054443
5.说一下对变量提高的理解

当JavaScript执行过程进入新函数时,这个函数内被声明的全部变量都会被移动导到函数最开始的地方。这种现象叫作提高。且被提高的只有变量的声明。javascript

函数执行时会先建立当前的上下文环境,其中这两点会产生“变量提高”的效果php

  • 变量定义
  • 函数声明(注意和函数表达式的区别)
6.说明this几种不一样的使用场景

做为构造函数时的执行 指向构造函数的对象css

做为对象属性时的执行 指向对象html

做为普通函数时的执行 指向window前端

call  bind apply 从新把this指向新对象java

7.建立10个li,点击的时候弹出对应的序号
var i
for (i = 0; i < 10; i++) {
    (function (i) {
        var a = document.createElement('a')
        a.innerHTML = i + '<br>'
        a.addEventListener('click', function (e) {
            e.preventDefault()
            alert(i)
        })
        document.body.appendChild(a)
    })(i)
}
8.如何理解做用域
*   自由变量
*   做用域链,即自由变量的查找
*   闭包的两个场景
9.实际开发中闭包的应用
// 闭包实际应用中主要用于封装变量,收敛权限
// 即把变量隐藏起来,不让外面拿到和修改
function isFirstLoad() {
    var _list = []

    return function (id) {
        if (_list.indexOf(id) >= 0) {
            return false
        } else {
            _list.push(id)
            return true
        }
    }
}

// 使用
var firstLoad = isFirstLoad()
firstLoad(10) // true          
firstLoad(10) // false
firstLoad(20) // true

// 在 isFirstLoad 函数外面,根本不可能修改掉 _list 的值
10.同步异步的区别是什么?分别举一个例子
同步会阻塞代码 而异步不会

alert 是同步 
setTimeout 是异步

eg:
console.log('1');
setTimeout(function(){
    console.log('2');
},200)
console.log('3');
-------------

console.log('1')
alert('2')
console.log('3');
11.一个关于setTimeout的笔试题
jq源码里面利用了js程序的单线程 写了setTimeout(function(){})来解决 等页面加载完;
------------------
console.log(1);
setTimeout(function(){
    console.log(2)
},0)
console.log(3)
setTimeout(function(){
    console.log(4)
},1000)
console.log(5)

>> 1 3 5 2 4
12.前端使用异步的场景
定时任务: setTimeout setInverval 
网络请求: ajax请求  动态<img>加载
事件绑定
13.Date 获取 2020-01-21格式的日期
function time(){
    var date = new Date();
    var year = date.getFullYear();
    var month = date.getMonth()+1;
    var day = date.getDate();
    return year+'-'+num_fn(month)+'-'+num_fn(day);
}
function num_fn(num){
    return num>=10? num : '0'+num
}
14.Math 获取随机字符串要求是长度一致的字符串格式
function randomAtr(){
         return Math.floor(Math.random()*1000000000)
         
         //或者
         //var num = Math.random()+'';
         //return num.slice(2,13)
}
15.能写一个能遍历对象和数组的的forEach函数
function forEach_fn(obj,fn){
var key;
if(obj instanceof Array){
    arr.forEach(function(item, index){
        fn(index, item)//遍历数组全部的元素
    })
}else{
    for(key in obj){
        fn(key, obj[key])
    }
}

}ajax

16.DOM是哪一种的基本数据结构

DOM树形结构json

17.DOM操做的经常使用API有哪些

建立型api:createElementcreateTextNodecloneNodecreateDocumentFragment后端

页面修改型API
修改页面内容的api主要包括:appendChildinsertBeforeremoveChildreplaceChildapi

节点查询型API
document.getElementById
document.getElementsByTagName
document.getElementsByName
document.getElementsByClassName
document.querySelector和document.querySelectorAll:经过css选择器来查找元素,注意选择器要符合CSS选择器的规则,使用的深度优先搜索来获取元素

节点关系型api

1.父关系型api

  • parentNode:Element的父节点多是Element,Document或DocumentFragment。
  • parentElement:与parentNode的区别在于,其父节点必须是一个Element,若是不是,则返回null

2.子关系型api

  • childNodes:返回一个即时的NodeList,表示元素的子节点列表,子节点可能会包含文本节点,注释节点等。
  • children:一个即时的HTMLCollection,子节点都是Element,IE9如下浏览器不支持。
  • firstNode:第一个子节点
  • lastNode:最后一个子节点
  • hasChildNodes方法:能够用来判断是否包含子节点。

3.兄弟关系型api

  • previousSibling:节点的前节点,若是该节点是第一个节点,则为null。
  • previousElementSibling:返回前元素节点,前一个节点必须是Element。
  • nextSibling:节点的后节点,若是该节点是最后一个节点,则为null。。
  • nextElementSibling:返回后元素节点,后一个节点必须是Element。

元素属性型api
setAttribute:根据名称和值修改元素的特性eg:element.setAttribute(name, value);
getAttribute:返回指定的特性名相应的特性值,若是不存在,则返回null或空字符串.

18.DOM节点的attr和property有何区别

property 只是一个JS对象的属性的修改
Attribute 是对html标签属性的修改

19.如何检测浏览器的类型

navigator.userAgent 加正则匹配

20.拆解url的各部分
href        完整的 URL。

protocol    当前 URL 的协议。
host        主机名和当前 URL 的端口号。
hostname    当前 URL 的主机名。
pathname    当前 URL 的路径部分。
port        当前 URL 的端口号。

hash        hash。从井号(#)开始)。
search        参数。从问号(?)开始的。
21.编写一个通用的事件监听函数
function bindEvent(elem,type,selector,fn){
    if(fn == null){
        fn = selector;
        selector = null;
    }
    elem.addEventListener(type,function(e){
        var target;
        if(selector){//有代理
            target = e.target;
            if(target.macthes(target)){
                fn.call(target,e)//从新指定this 并传参e
            }
        }else{//无代理
            fn(e);
        }
    })
    
}
22.描述事件冒泡的过程
沿着DOM树形结构,一层层网上冒泡,
一直到 最顶端或者出现阻止冒泡命令
e.stopPropagation();
冒泡的应用 代理
23.对于一个无限下拉加载图片的页面,如何给每一个图片绑定事件
事件委派

24.手动编写一个ajax,不依赖第三方库

1.建立ajax对象
2.接收服务器
3.发送请求
4.接收返回值

var oAjax = new XMLHttpRequest();
oAjax.open("GET","text.json",false);
oAjax.send();
oAjax.onreadystatechange(function(){
    if(oAjax.readyState == 4){
        if(oAjax.status == 200){
            console.log(oAjax.responseText)
        }
    }
})
25.状态码的说明;
  • 0开头 未初始化 尚未调用open()方法;
  • 1开头 载入 已调用open()方法,正在发送请求
  • 2开头 载入完成 send()方法完成,已收到所有响应内容
  • 3开头 解析 正在解析响应内容
  • 4开头 完成 响应内容解析完成,能够再客户端调用
  • 5开头 服务器错误
26.跨域的几种实现方式
1. 服务器请求头修改
2. 重定向代理
3. jsonp
jsonp跨域 原生实现:
 <script>
    var script = document.createElement('script');
    script.type = 'text/javascript';

    // 传参并指定回调执行函数为onBack
    script.src = 'http://www.....:8080/login?user=admin&callback=onBack';
    document.head.appendChild(script);

    // 回调执行函数
    function onBack(res) {
        alert(JSON.stringify(res));
    }
 </script>
26.GET POST区别;
get 安全性差 容量低 有缓存 经过url传  通常用于获取数据

post 安全性高 容量高 无缓存  通常用于用户注册

27.描述cookies、sessionStrorage localStrorage的区别;
  • cookies

    • 存储量小 只有4K,
    • 全部http请求都带着,会影响获取资源的效率
    • 封装才能用 document.cookies
    • 能够设置过时时间;服务器也能访问设置;
  • sessionStrorage

    • 存储量大 最大5M;
    • 简单易用
    • 不能设置过时时间,关闭浏览器会删除
  • localStrorage

    • 存储量大 最大5M;
    • 简单易用
    • 须要手动删除缓存
localStorage.setItem("saveData", JSON.stringify(setData) ); //存值 补充:存储前先用JSON.stringify()将json对象转字符串
    
localStorage.getItem("saveData”) //取值 补充:JSON.parse(ss) 将json字符串转为 json格式
    
localStorage.removeItem("saveData”);//删值
28.从输入url到html的详细过程
浏览器根据DNS服务器获得域名的IP地址

向这个IP的机器发送https/https请求

服务器收到、处理并返回请求

浏览器获得返回内容
29.window.onload和DOMContentLoaded的区别
window.onload:页面的所有资源加载完才会执行,包括图片、视频等
DOMContentLoaded:DOM渲染完便可执行,此时图片、视频尚未加载完
30.性能优化
性能优化:
多使用内存、缓存或其余方法   
减小cpu计算、减小网络   

加载资源优化:
1静态资源的合并压缩 
2静态资源缓存 
3使用CDN让资源加载更快  
4使用SSR后端渲染,数据直接输出到HTML中

渲染优化:
1.CSS放前面 JS放后面
2.懒加载(图片懒加载、下拉加载更多)
3.减小DOM查询,对DOM查询作缓存  
4.减小DOM操做,多个操做尽可能合并在一块儿执行
5.事件节流
6.尽早执行操做(如DOMContentLoaded)

Part2

1.移动端怎样处理 移动端 1px 被 渲染成 2px 问题
1 局部处理
meta标签中的 viewport属性 ,initial-scale 设置为 1 
rem 按照设计稿标准走,外加利用transfrome 的scale(0.5) 缩小一倍便可;
2 全局处理
meta标签中的 viewport属性 ,initial-scale 设置为 0.5
    rem 按照设计稿标准走便可
2.let var const
名字 特性说明
var 变量; 能重复声明; 函数级; 顶层对象的属性; 不限制修改
let 变量; 不能重复声明; 块级; 不属于顶层对象的属性; 可修改
const 声明和赋值必须是同时进行; 常量; 不能重复声明; 块级; 不属于顶层对象的属性; "不"可修改[ 实际上并不是彻底不可修改。const声明建立一个值的只读引用,对于基本类型不可修改,但若是是复合类型时,只要不修改引用,修改里面的值是能够的];
代码演示:
console.log(k_name); //变量提高;输出undefined
var k_name = "jerry";
console.log(k_name);//输出jerry

console.log('1',k_age);//不会变量提高;在定义以前报错不能用
let k_age = "12";
console.log('2',k_age);

//const基础类型时
const may_class = 3;
may_class = 4;//基础类型时 报错

//const复杂类型时
const all_class = [1,2,3];
all_class[0] = 9; //不报错
console.log(all_class);//修改为功 》[9, 2, 3]
3.编写个简单的url解析和赋值替换
var url = "http://witmax.cn/index.php?key0=0&key1=1&key2=2";

// 返回url的拼接对象
function parseQueryString(argu) {
    var str = argu.split('?')[1];
    var result = {};
    var temp = str.split('&');
    for (vari = 0; i < temp.length; i++) {
        var temp2 = temp[i].split('=');
        result[temp2[0]] = temp2[1];
    }
    return result; //url上的所有参

}

// 拓展一下 对页面url操做, 只有一个参 那么查找url上的参数并返回值, 若是有两个参数查找更新或删除参数
function urlSearch(argu ,newValue) {
    var str = window.location.search.slice(1);
    var result = {};
    var temp = str.split('&');
    for (vari = 0; i < temp.length; i++) {
        var temp2 = temp[i].split('=');
        result[temp2[0]] = temp2[1];
    }
    return result; //url上的所有参

    if (newValue !== undefined) {
        if (newValue !== null) {
            result[argu] = newValue;//更新值
        }else {
            delete result[argu];//删除值
        }
        // 更新参数后从新拼接 并替换url的连接
        var str = '';
        for(k in ee){
            str += (k + '=' + ee[k] + '&');
        }
        str = str.replace(/&$/,'');
        // var newUrl = window.decodeURIComponent(argu.split('?')[0]+'?'+str);
        var newUrl = window.location.href.split('?')[0]+'?'+str;
        window.history.pushState(null, document.title,newUrl);
        // return newUrl;
    }else{
        return result[argu];
    }
}
4.看看如下分别输出什么
if([] == false){ alert(1)} //在比较前false转成0 [].toString()转成了空字符串 空字符串转成0, ;因此true
 if({} == false){ alert(2)}//在比较前false转成0, {}.toString()转成"[object Object]" 不等
 
 if([]){ alert(3)}
 
 //引用类型(数组 对象 函数)的比较并不是值的比较:两个对象保含一样的属性及相同的值 它们是不相等的。 各个因此元素彻底相等的两个数组也不相等。
 if([1] == [1]){ alert(4)}
 if({x:1} == {x:1} ){ alert(4)}

引用类型的比较均是引用的比较:当且仅当它们引用同一个基对象时,它们才相等 eg:

var a = [];
var b = a; //变量b引用同一个数组
b[0] = 1;
console.log(b); // [1]
console.log(a); // [1]

a === b; //true: a和b引用同一个数据,所以它们相等
 
 
###### 给定一个整数数组,找出其中两个数相加等于目标值
5.给定数组及目标值 nums = [2,7,11,15] ,target = 9 由于nums[0] + nums[1] = 2 + 7 = 9 返回[0,1]
var twoSum = function(nums, target) {
var cbArr = [];
for(var i = 0; i< nums.length; i++){
    if(cbArr.indexOf(i) == -1){ //除去已经在结果里面的 避免重复
        for(var k = 0; k< nums.length; k++){
            if((i !== k) && (nums[i]+ nums[k] == target)){
                cbArr.push(i,k);
            }
        }
    }
}
return cbArr;
};
6.字符串的左旋转操做是把字符串前面的若干个字符转移到字符串的尾部。请定义一个函数实现字符串左旋转操做的功能。
eg:
输入: s = "lrloseumgh", k = 6
输出: "umghlrlose"

var reverseLeftWords = function(s, n) {     
    return s.slice(n).concat(s.slice(0,n))
};
8.给定一个分别输出一下的值:
function Foo(){
    getName = function(){alert(1)};
    return this;
}

Foo.getName = function(){alert(2)};
Foo.prototype.getName = function(){alert(3)};
var getName = function(){alert(4)};
function getName(){alert(5)};


Foo.getName(); 
getName();   
Foo().getName();     
getName();             
new Foo().getName();   

答案----
//2 4 1 1 3
9.输出一下值 并分析:
function fn(a) {

    console.log(a)  
    var a = 123;    
    console.log(a)  
    function a() {}
    console.log(a)  
    
    var b = function() {
        console.log('bb','1')
    }
    console.log(b)  
    b(); 
    function b() {
        console.log('bb','2')
    }
}
fn(1)


 --------------------------
a的分析:
进入fn 虽然带参数a进去 可是 进到函数   
1 最开始a有声明式函数,会直接挂载在函数下,因此第一个打印是function;
2 第一个打印后立刻就给a赋值了123, 因此第二个打印是123;
3 下一行 a的声明式函数比2执行还早 因此不影响 第三个打印是123;

--------------------------
b的分析:
1 b无论属于谁打印确定是function;
2 最开始b有声明式函数,会直接挂载在函数下,而后var 从新赋值了b的函数 因此 输出是

答案:function  123 123    function  bb 1
10. 输出下面值
var i= 10;
function a(){
    i = 20;
    console.log(i); // 20;
    for(var i=0; i<6;i++){
        console.log(i) // 0-5
    }
    console.log(this.i); //10 :window.i  外部环境不能访问内部环境中的任何变量和函数
    console.log(i);     //6  : 当前的局部变量在循环时被赋值为6
}
a();
console.log(i) //10 :window.i  外部环境不能访问内部环境中的任何变量和函数
11.js函数add(1)(2)(3)(4)的累加

想法:写个闭包每次返回函数都带参累加,知道参数没有再也不执行函数 则返回累加的和。
先写个暴力概念版 只要我写得够多就能'知足'题目要求:

function add(a){
    let sum = a;
    return function count_fn1(b){
        sum +=b;
        return function count_fn1(c){
            sum +=c;
                return function count_fn1(d){
                sum +=d;
                return sum;
            };
        };
    }
}
add(1)(2)(3)(4)//10
全然不顾灵活不灵活拓展不拓展~ 老子就是干

不 咱们不能仅苟且的活着!要灵活要自由~

function add(a){
    let sum = a;
    return function count_fn(b){
        sum +=b;
        return count_fn(b);
    }
}
//改为递归 是能够灵活执行多少次函数达到累加。问题 输出的也是函数 没有把累计的值输出出来呀!

这时咱们要了解一个知识点:当咱们直接对函数使用alert()console.log()时,函数的toString()方法会被调用。并且函数的toString()方法是能够复写的

最终版:

function add(x) {
    var sum = x;
    var tmp = function (y) {
        sum = sum + y;
        return tmp;
    };
    tmp.toString = function () {
        return sum;
    };
    return tmp;
}
console.log(add(1)(2)(3));  //6
12. 输出是什么?
(() => {
  let x, y
  try {
    throw new Error()
  } catch (x) {
    (x = 1), (y = 2)
    console.log(x)
  }
  console.log(x)
  console.log(y)
})()

答案:
1 undefined 2;
分析:
catch 代码块接收参数 x。当咱们传递参数时,这与以前定义的变量 x 不一样 。这个 x 是属于 catch 块级做用域的且 默认了设置了等于1; 因此第一个打印1;
外面x依然没赋值;因此第二个打印`undefined`;
y最开始let声明了,后面赋值了2,因此第二个打印2;
13. 输出是什么?
let person = { name: "Lydia" };
const members = [person];
person = null;

console.log(members);


答案:[{ name: "Lydia" }];
分析:  
当设置两个对象彼此相等时,它们会经过 引用进行交互。可是当将`引用从一个变量分配至另外一个变量时`,实际上是执行了 复制 操做。 因此它们的引用并不一样
14. 输出是什么?
const settings = {
  username: "lydiahallie",
  level: 19,
  health: 90
};

const data = JSON.stringify(settings, ["level", "health"]);
console.log(data);

答案:"{"level":19, "health":90}"
分析:
[JSON.stringify(value[, replacer[, space]])](https://www.runoob.com/js/javascript-json-stringify.html)//老子还有第二第三个参数可传哦。
// 参数一:转换的值
// 参数二:替代者。用于转换结果的函数或数组。
// 参数三:控制空格

JSON.stringify的第二个参数是 替代者(replacer). 替代者(replacer)能够是个函数或数组,用以控制哪些值如何被转换为字符串。
若是替代者(replacer)是个 数组 ,那么就只有包含在数组中的属性将会被转化为字符串。在本例中,只有名为"level" 和 "health" 的属性被包括进来, "username"则被排除在外。 data 就等于 "{"level":19, "health":90}”.
15.懒加载预加载

懒加载: 图片的懒加载作法 都是把连接存放在 data-src中,监听onscroll时,一个个加载出来;

预加载:将全部所需的资源提早请求加载到本地,这样后面在须要用到时就直接从缓存取资源。
实现预加载的几种办法:

//使用img标签 
<img src="http://pic26.nipic.com/20121213/6168183 0044449030002.jpg" style="display:none”/> 

------------
//js 使用Image对象
<script src="./myPreload.js"></script>

//myPreload.js文件
var image= new Image()
image.src="http://pic26.nipic.com/20121213/6168183 004444903000 2.jpg"

-------------
//使用PreloadJS库

-------------
//使用XMLHttpRequest对象,虽然存在跨域问题,但会精细控制预加载过程
var xmlhttprequest=new XMLHttpRequest();
xmlhttprequest.onreadystatechange=callback;
xmlhttprequest.onprogress=progressCallback;
xmlhttprequest.open("GET","http://image.baidu.com/mouse,jpg",true);
xmlhttprequest.send();
function callback(){
  if(xmlhttprequest.readyState==4&& xmlhttprequest.status==200){
    var responseText=xmlhttprequest.responseText;
  }else{
     console.log("Request was unsuccessful:"+xmlhttprequest.status);
  }
}
function progressCallback(e){
    e=e || event;
    if(e.lengthComputable){
    console.log("Received"+e.loaded+"of"+e.total+"bytes")
    }
}
16.break continue return throw分别是?
1.break 跳出循环
2.continue 跳出本次循环,进入下次循环
3.return 停止跳出当前函数
4.throw 异常信息;停止程序抛出异常,可用于停止程序
17.内存泄漏

定义:内存泄漏指任何对象在您再也不拥有或须要它以后仍然存在。
后果:变慢,崩溃,延迟大等:
哪些会形成:

  • 定时器未清除
  • 闭包、控制台日志、循环(在两个对象彼此引用且彼此保留时,就会产生一个循环)
  • dom清空时,还存在引用

避免策略

  • 减小没必要要的全局变量,或者生命周期较长的对象,及时对无用的数据进行垃圾回收;
  • 注意程序逻辑,避免“死循环”之类的 ;
  • 避免建立过多的对象 原则:不用了的东西要及时归还。
  • 减小层级过多的引用
18.重绘和回流(重排)是什么,如何避免?

重绘:改变元素的样式。例如宽高颜色。
回流(重排):布局和样式都改变。

重排必定重绘,重绘不必定重排。

减小重绘和重排的方法

  • 不在布局信息改变时作DOM查询
  • 使用cssText或者className一次性改变属性
  • 使用fragment
  • 对于屡次重排的元素,如动画,使用绝对定位脱离文档流,让他的改变不影响到其余元素
  • 使用translate替代top
相关文章
相关标签/搜索