css+js面试题整理

js面试题整理

链接

JavaScript原型,原型链 ? 有什么特点?

原型链
每个对象拥有一个原型对象,通过 proto 指针指向上一个原型 ,并从中继承方法和属性,同时原型对象也可能拥有原型,这样一层一层,最终指向 null。这种关系被称为原型链 (prototype chain),通过原型链一个对象会拥有定义在其他对象中的属性和方法。

关系:instance.constructor.prototype = instance.proto

特点:

JavaScript对象是通过引用来传递的,我们创建的每个新对象实体中并没有一份属于自己的原型副本。当我们修改原型时,与之相关的对象也会继承这一改变。

当我们需要一个属性的时,Javascript引擎会先看当前对象中是否有这个属性, 如果没有的话,

就会查找他的Prototype对象是否有这个属性,如此递推下去,一直检索到 Object 内建对象。

function Func(){}
Func.prototype.name = “Sean”;
Func.prototype.getInfo = function() {
return this.name;
}
var person = new Func();//现在可以参考
var person = Object.create(oldObject);

console.log(person.getInfo());
//它拥有了Func的属性和方法
//"Sean"   

console.log(Func.prototype);    
// Func { name="Sean", getInfo=function()}
  • Symbol 作为构造函数来说并不完整,因为不支持语法 new Symbol(),但其原型上拥有 constructor
    属性,即Symbol.prototype.constructor。 引用类型
    constructor属性值是可以修改的,但是对于基本类型来说是只读的,当然 null 和 undefined 没有
    constructor 属性。
  • proto 是每个实例上都有的属性,prototype 是构造函数的属性,在实例上并不存在,所以这两个并不一样,但 p.proto 和 Parent.prototype 指向同一个对象。
  • proto 属性在 ES6 时被标准化,但因为性能问题并不推荐使用,推荐使用 Object.getPrototypeOf()。
  • 每个对象拥有一个原型对象,通过 proto 指针指向上一个原型
    ,并从中继承方法和属性,同时原型对象也可能拥有原型,这样一层一层,最终指向 null,这就是原型链。

js的面向对象

  • 一切事物皆对象
  • 对象具有封装和继承特性
  • 对象与对象之间使用消息通信,各自存在信息隐藏

面向对象仅仅是一个概念或者编程思想而已,

面向对象的语言最基本的标志就是类的概念。什么是类?类是包含多个属性和方法的集合,类的实例即对象。

什么是事件循环(Event Loop)

事件循环
javascript 调控同步和异步任务的机制称为事件循环,首先来看事件循环机制的可视化描述
所以的同步任务都在主线程上执行,形成一个执行栈。
主线程之外,还存在一个“消息队列”。只要异步操作执行完成,就到消息队列中排队。
一旦执行栈中的所有同步执行完毕,系统就会按次序读取消息队列中的异步任务,于是被读取的异步任务结束等待状态,进行执行栈,开始执行。
主线程不断的重复上面的第三步。
【循环】
从代码执行顺序的角度来看,程序最开始是按代码的顺序执行代码的,遇到同步任务,立刻执行;遇到异步任务,则这是调用异步函数发起异步请求。此时,异步任务开始执行异步操作,执行完成后到消息队列中排队。程序按照代码的顺序执行完毕后,查询消息队列中是否哟得带的消息。如果有,则按照次序从消息队列中把消息放到执行栈中执行。执行完毕后,再从消息队列中获取消息,再执行,不断重复。

执行栈与事件队列
堆(heap)和栈(stack)中来加以区分。其中,堆里存放着一些对象。而栈中则存放着一些基础类型变量以及对象的指针。

Vue的双向数据绑定原理是什么?

vue是采用数据劫持,并且使用发布-订阅者的开发模式。原理是观察者observer通过Object.defineProperty()来劫持到各个属性的getter setter,在数据变动的时候,会被observer观察到,会通过Dep通知数据的订阅者watcher,之后进行相应的视图上面的变化

  • VUE实现双向数据绑定的原理就是利用了Object.defineProperty()这个方法重新定义了对象获取属性值(get)和设置属性值(set)的操作来实现的。
  • vue数据双向绑定是通过数据劫持Object.defineProperty( )结合发布者-订阅者模式的方式来实现的

如何实现浏览器内多个标签页之间的通信? (阿里)

WebSocket、SharedWorker;

也可以调用localstorge、cookies等本地存储方式;

localstorge另一个浏览上下文里被添加、修改或删除时,它都会触发一个事件,

我们通过监听事件,控制它的值来进行页面信息通信;

注意quirks:Safari 在无痕模式下设置localstorge值时会抛出 QuotaExceededError 的异常

js如何判断数组是Array类型

在说明如何判断一个对象为数组类型前,我们先巩固下js的数据类型,

js一共有六大数据类型:number、string、object、Boolean、null、undefined。

var str="string";
console.log(typeof str); //string
var num=1;
console.log(typeof num); //number
var bn=false;
console.log(typeof bn); //boolean
var a;
console.log(typeof a); //undfined
var obj = null;
console.log(typeof obj); //object
var doc = document;
console.log(typeof doc);//object
var arr = [];
console.log(arr); //object
var fn = function(){};
console.log(typeof fn); //function

除了前四个类型外,null、对象、数组返回的都是object类型;

对于函数类型返回的则是function,再比如typeof(Date),typeof(eval)等。接下来进入正题,
js判断数组类型的方法。

  • 方法一: 使用instanceof方法

    instanceof 用于判断一个变量是否某个对象的实例,左边操作数是一个对象,右边操作数是一个函数对象或者函数构造器。

    原理是通过判断左操作数的对象的原型链上是否具有右操作数的构造函数的prototype属性。

    a instanceof b?alert("true"):alert("false")
//注意b值是你想要判断的那种数据类型,不是一个字符串,比如Array。

举一个例子:
    var arr=[];
    console.log(arr instanceof Array) //返回true
  • 方法二: 使用constructor方法

    在W3C定义中的定义:constructor

    属性返回对创建此对象的数组函数的引用,就是返回对象相对应的构造函数。

    从定义上来说跟instanceof不太一致,但效果都是一样的。

    那么判断各种类型的方法:

    console.log([].constructor == Array);  //true
    console.log({}.constructor == Object);  //true
    console.log("string".constructor == String); //true
    console.log((123).constructor == Number);  //true
    console.log(true.constructor == Boolean);  //true
注意:

使用instaceof和construcor,被判断的array必须是在当前页面声明的!

比如,一个页面(父页面)有一个框架,框架中引用了一个页面(子页面),
在子页面中声明了一个array,并将其赋值给父页面的一个变量,
这时判断该变量,Array ==object.constructor;会返回false;

原因:

1、array属于引用型数据,在传递过程中,仅仅是引用地址的传递。

2、每个页面的Array原生对象所引用的地址是不一样的,在子页面声明的array,所对应的构造函数,
是子页面的Array对象;父页面来进行判断,使用的Array并不等于子页面的Array。
  • 方法三: 使用Object.prototype.toString.call(arr) === '[object Array]'方法
function isArray(o) {
      return Object.prototype.toString.call(o);
    }
    var arr=[2,5,6,8];
    var obj={name:'zhangsan',age:25};
    var fn = function () {}
    console.log(isArray(arr)); //[object Array]
    console.log(isArray(obj)); //[object Object]
    console.log(isArray(fn));  //[object function]
  • 方法四:ES5定义了Array.isArray:

    Array.isArray([]) //true

合并多个对象并且去重的2种写法(es6)

let objOne = {a:1};
let objTwo = {b:2};
let objThree = {b:4,c:5};
let obj = Object.assign(objOne,objTwo,objThree);
console.log(obj)    // {a:1,b:4,c:5}
let obj1={...objOne,...objTwo,...objThree};
console.log(obj1)   // {a:1,b:4,c:5}

js扩展运算符(spread)是三个点(…)

// ES6 的写法
var arr1 = [0, 1, 2];
var arr2 = [3, 4, 5];
arr1.push(...arr2);

合并两个数组并去重(ES5和ES6两种方式实现)

https://blog.csdn.net/qingmengwuhen1/article/details/79876813

  • ES6实现方式

let arr1 = [1, 1, 2, 3, 6, 9, 5, 5, 4]
let arr2 = [1, 2, 5, 4, 9, 7, 7, 8, 8]
function uniqueArr(arr1,arr2) {
    //合并两个数组
    arr1.push(...arr2)
    //或者arr1 = [...arr1,...arr2]
    //去重
    let arr3 = Array.from(new Set(arr1))
    //let arr3 = [...new Set(arr1)]
    console.log(arr3) 
}

uniqueArr(arr1,arr2)

注:new Set()接收一个数组,并且数组中的元素是唯一的。Array.from()能把伪数组转化为真正的数组。

  • ES5实现方式1
var arr1 = [1, 1, 2, 3, 6, 9, 5, 5, 4]
var arr2 = [1, 2, 5, 4, 9, 7, 7, 8, 8]
function uniqueArr(arr1, arr2){
    var arr3 = arr1.concat(arr2)
    var arr4 = []
    for(var i=0,len=arr3.length; i<len; i++) {
        if(arr4.indexOf(arr3[i]) === -1) {
            arr4.push(arr3[i])
        }
    }
    console.log(arr4)
} 
uniqueArr(arr1, arr2)
    

this指向

  • ① this指向的,永远只可能是对象!

  • ② this指向谁,永远不取决于this写在哪!而是取决于函数在哪调用。

  • ③ this指向的对象,我们称之为函数的上下文context,也叫函数的调用者。

  • 通过函数名()直接调用:this指向window

 
function func(){
    console.log(this);
}
        
//① 通过函数名()直接调用:this指向window
func(); // this--->window

  • ② 通过对象.函数名()调用的:this指向这个对象
function func(){
    console.log(this);
}

//② 通过对象.函数名()调用的:this指向这个对象
// 狭义对象
var obj = {
name:"obj",
func1 :func
};
obj.func1(); // this--->obj

// 广义对象
document.getElementById("div").onclick = function(){
this.style.backgroundColor = "red";
}; // this--->div
  • ③ 函数作为数组的一个元素,通过数组下标调用的:this指向这个数组
function func(){
    console.log(this);
}

//③ 函数作为数组的一个元素,
通过数组下标调用的:
this指向这个数组
var arr = [func,1,2,3];
arr[0]();  // this--->arr
  • ④ 函数作为window内置函数的回调函数调用:this指向window( setInterval setTimeout 等)

function func(){
    console.log(this);
}

//④ 函数作为window内置函数的回调函数调用:
this指向window
setTimeout(func,1000);// this--->window
//setInterval(func,1000);
  • ⑤ 函数作为构造函数,用new关键字调用时:this指向新new出的对象

function func(){
    console.log(this);
}

//⑤ 函数作为构造函数,
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值