(新)字节跳动面试真题

4 篇文章 0 订阅

js脚本加载问题,async、defer问题

  • 如果依赖其他脚本和DOM结果,使用defer
  • 如果与DOM和其他脚本依赖不强时,使用async

image.png

如何判断一个对象不是空对象

Object.keys(obj).length === 0

在线编程,getUrlParams(url,key);就是简单的获取url的某个参数的问题,但是要考虑多个便捷,多个返回值等

getUrlParams(url) {
    const _url = url || window.location.href;
    console.log(_url)
    const _urlParams = _url.match(/([?&])(.+?=[^&]+)/igm);
    console.log(_urlParams)
  
    return _urlParams ? _urlParams.reduce((a, b) => {
    const value = b.slice(1).split('=');
  
    a[value[0]] = value[1]
  
    return a;
  
    }, {}) : {};
  
    }
console.log(this.getUrlParams('?name=wuweigang&age=25&school=bj university'))

<script src='xxx' />外部js文件先加载还是onload先执行,为什么?

onload是左右加载完成之后才执行的

怎么是事件监听,两种

onclick和addEventListener

事件传播机制(事件流)

冒泡和捕获

原型链和原型链的继承?

  • 其实[[prototype]]__proto__意义相同,均表示对象的内部属性,其值指向对象原型。所有[[prototype]]链最终都会指向内置的Object.prototype,其包含了javascript中许多通用的功能
  • 为什么能创建‘类’,借助一种特殊的属性:所有的函数默认都会拥有一个名为prototype的共有且不可枚举的属性,它会执行另一个对象,这个对象通常被称为函数的原型。
function Person(name){
	this.name = name
}
Person.prototype.constructor = Person
  • 在发生new构造函数调用时,会将创建的新对象[[prototype]]链接到Person.prototype指向的对象,这个机制被称为原型链继承
  • 方法定义在原型上,属性定义在构造函数上
  • 首先要说下js原型和实例的关系:每一个构造函数(constructor)都有一个原型对象(prototype),这个原型对象包含一个指向此构造函数的指针属性,通过new进行构造函数调用生成的实例,此实例包含一个指向原型对象的指针,也就是通过[[prototype]]链接到了这个原型对象
  • 然后说一下js中属性的查找:当我们试图引用实例对象的某个属性时,是按照这样的方式去查找的,首先查找实例对象上是否有这个属性,如果没有找到,就去构造这个实例对象的prototype所指向的对象上查找,如果还找不到,就从这个prototype对象所指的构造函数的prototype原型对象上查找
  • 什么是原型链:这样逐级查找形似一个链条,且通过[[Prototype]]属性链接,所以被称为原型链
  • 什么是原型链继承,类比类的继承:当有两个构造函数A和B,将一个构造函数A的原型对象,通过其[[Prototype]]属性链接到另外一个B构造函数的原型对象时,这个过程被称之为原型继承
什么是原型链(标准答案更正确的解释)

当对象查找一个属性时,如果没有在自身找到,那么就会查找自身的原型,如果原型还没有找到,那么会继续查找原型的原型,直到找到Object.prototype的原型是,此原型为null,查找停止。这种通过原型链接的逐级向上的查找链被称为原型链

什么是原型继承?

一个对象可以使用另一个对象的属性或者方法,就称之为继承。具体是通过将这个对象的原型设置为另一个对象,这样根据原型链的规则,如果查找一个对象属性且在自身不存在时,就会查找另一个对象,相当于一个对象可以使用另一个对象的属性和方法

说下对js的了解

javascript是一种轻量级的解释执行的而非编译的脚本语言。

不需要预先编译而是在程序运行中逐行解释并执行。由ECNAScript、文档对象模型(DOM)和浏览器对象模型(BOM)组成

是基于原型的动态语言,主要独特特性有this、原型和原型链。严格意义上来说分为语言标准部分(ECMAScript)+宿主环境部分

语言标准部分

2015年发布ES6,引入诸多新特性使得能够编写大型项目变成可能,标准自2015之后以年号代号,每年一更

宿主环境部分

  • 在浏览器宿主环境包括DOM+BOM
  • 在node,宿主环境包括一些文件、数据库、网络、与操作系统的交互等

数组能够调用的函数有哪些?

  • push 向数组的末尾添加一个或多个元素,并返回新的长度
  • pop 向删除并返回数组的最后一个元素
  • splice 删除元素,并向数组添加新元素
  • slice 从某个已有的数组返回选定元素
  • shift 删除并返回数组的第一个元素
  • unshift 向数组的开头添加一个或更多元素,并返回新的长度
  • sort 排序
  • reverse 颠倒数组中的元素
  • concat 链接两个或者更多的数组,并返回结果
  • join 将数组所有元素放入一个字符串
  • find
  • findindex
  • map/filter/reduce等函数式编程方法
  • 还有一些原型链上的方法:toString/valueOf

如何判断数组的类型

Array.isArray

函数中的arguments是数组吗?类数组转数组的方法

是类数组,伪数组,是属于鸭子类型的范畴,长的像数组,

  • …运算符
  • Array.from
  • Array.prototype.slice.apply(arguments)

用过typeScript嘛?它的作用是什么?

为js添加类型支持,以及提供罪行的es语法的支持,是利于团队协作和排错,开发大型项目

PWA使用过吗?serviceWorker的使用原理是啥?

渐进式网络应用(PWA是谷歌在2015年底提出的概念。基本上算是web应用程序,但在外观和感觉上与原生app类似。支持PWA的网站可以提供脱机工作、推送通知和设备硬件访问等功能。

Service Worker是浏览器在后台独立于网页运行的脚本,他打开了通向不需要网页或用户交互的功能的阀门。现在,它们已包括如推送通知和后台同步等功能。将来,Service Worker将会支持如定期同步或地理围栏等其他功能。

如果一个构造函数,bind了一个对象,用这个构造函数创建出的实例会继承这个对象的属性吗?为什么?

不会继承。因为根据this绑定四大规则,new绑定的优先级高于bind显示绑定,通过new进行构造函数调用时,会创建一个新对象,这个新对象会代替bind的对象绑定,作为函数的this,并且在此函数没有返回对象的情况下,返回这个新建的对象

箭头函数和普通函数有啥区别,箭头函数能当构造函数嘛?

  • 普通函数通过function关键字定义,this无法结合词法作用域使用,在运行绑定,只取决于函数的调用方式,在哪里被调用,调用位置。(取决于调用者,和是否独立运行)
  • 箭头函数使用被称为‘胖箭头’的操作=>定义,箭头函数不应用普通函数this绑定的四种规则,而是根据外层(函数或全局)的作用域来决定this,且箭头函数的绑定无法被修改(new也不行)
  • 箭头函数常用与回调函数中,包括时间处理器或定时器
  • 箭头函数和 var self = this,都试图取代传统的this运行机制,将this的绑定拉回到词法作用域
  • 箭头函数没有原型、this、super、arguments、new.target
  • 不能通过new关键字调用
    • 一个函数内部有两种方法:[[call]]和[[Construct]],在通过new进行函数调用时,会执行[[construct]]方法,创建一个实例对象,然后再执行这个函数体,将函数的this绑定在这个实例对象上
    • 当直接调用时,执行[[Call]]方法,直接执行函数体
    • 箭头函数没有[[Construct]]方法,不能被用作构造函数调用,当使用new进行函数调用

知道ES6的class嘛?static关键字有了解嘛?

被static修饰的属性和方法都是静态方法和属性,只能被类名调用,不能被实例化对象调用。同时也不能被子类继承,换句话说它属于当前这个类的。

ES6class 可以看作只是一个语法糖 ,它的绝大部分功能,ES5 都可以做到,新的 class 写法只是让对象原型的写法更加清晰、更像面向对象编程的语法

image.png

事件循环机制(Event Loop)

事件循环机制从整体上高速我们javascript代码的执行循序,Event Loop即事件循环,是指浏览器或Node的一种解决javascript单线程运行时不会阻塞的一种机制,也就是我们经常使用异步的原理。

先执行宏任务队列,然后执行微任务队列,然后开始下一轮事件循环、继续先执行宏任务,再执行微任务队列。

  • 宏任务:script/setTimeout/setInterval/setImmediate/I/O/UI Rendering
  • 微任务:process.nextTick()/Promise

上述的setTimeoutsetInterval等都是任务源,真正进入任务队列的是他们发布的任务

优先级

  • setTimeout = setInterval 一个队列
  • setTimeout > setImmediate
  • process.nextTick > Promise

扁平化数组

数组扁平化是指将一个多维数组变为一维数组

function flatten(arr){
	let result = []

	for(let i = 0; i< arr.length;i++){
		if(Array.isArray(arr[i])){
			result = result.concat(flatten(arr[i]))
		}else{
			result = result.concat(arr[i])
		}

	}

	return result
}
const a = [1,[2,[3,4]]]
console.log(flatten(a))

实现柯里化

维基百科上说道:柯里化,英语:Currying(果然是满满的英译中的既视感),是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数而且返回结果的新函数的技术。

通俗一点:是指这样一个函数,它接收函数A,并且能返回一个新的函数,这个新的函数能够处理函数A的剩余参数。

// 普通的add函数
function add(x, y) {
    return x + y
}

// Currying后
function curryingAdd(x) {
    return function (y) {
        return x + y
    }
}

add(1, 2)           // 3
curryingAdd(1)(2)   // 3
function createCurry(func,args){
	var argity = func.length;
	var args = args || []

	return function(){
		var _args = [].slice.apply(arguments)
		args.push(..._args)

		if(args.length < argity){
			return createCurry.call(this,func,args)
		}

		return func.apply(this.,args)
	}
}

数组去重

Array.from(new set([1,1,2,2,]))

let闭包

let会产生临时性死区,在当前的执行上下文中,会进行变量提升,但是未被初始化,所以在执行上下文执行阶段,执行代码如果还没有执行到变量赋值,就引用此变量就会报错,此变量未初始化

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

搞文艺的猿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值