如何取得对象非原型链上的属性?

应用后hasOwnProperty()办法来判断属性是否属于原型链的属性:

function iterate(obj){   var res=[];   for(var key in obj){        if(obj.hasOwnProperty(key))           res.push(key+': '+obj[key]);   }   return res;} 

一个 tcp 连贯能发几个 http 申请?

如果是 HTTP 1.0 版本协定,个别状况下,不反对长连贯,因而在每次申请发送结束之后,TCP 连贯即会断开,因而一个 TCP 发送一个 HTTP 申请,然而有一种状况能够将一条 TCP 连贯放弃在沉闷状态,那就是通过 Connection 和 Keep-Alive 首部,在申请头带上 Connection: Keep-Alive,并且能够通过 Keep-Alive 通用首部中指定的,用逗号分隔的选项调节 keep-alive 的行为,如果客户端和服务端都反对,那么其实也能够发送多条,不过此形式也有限度,能够关注《HTTP 权威指南》4.5.5 节对于 Keep-Alive 连贯的限度和规定。

而如果是 HTTP 1.1 版本协定,反对了长连贯,因而只有 TCP 连接不断开,便能够始终发送 HTTP 申请,继续一直,没有下限; 同样,如果是 HTTP 2.0 版本协定,反对多用复用,一个 TCP 连贯是能够并发多个 HTTP 申请的,同样也是反对长连贯,因而只有一直开 TCP 的连贯,HTTP 申请数也是能够没有下限地继续发送

继承

原型链继承

function Animal() {    this.colors = ['black', 'white']}Animal.prototype.getColor = function() {    return this.colors}function Dog() {}Dog.prototype =  new Animal()let dog1 = new Dog()dog1.colors.push('brown')let dog2 = new Dog()console.log(dog2.colors)  // ['black', 'white', 'brown']

原型链继承存在的问题:

  • 问题1:原型中蕴含的援用类型属性将被所有实例共享;
  • 问题2:子类在实例化的时候不能给父类构造函数传参;

借用构造函数实现继承

function Animal(name) {    this.name = name    this.getName = function() {        return this.name    }}function Dog(name) {    Animal.call(this, name)}Dog.prototype =  new Animal()

借用构造函数实现继承解决了原型链继承的 2 个问题:援用类型共享问题以及传参问题。然而因为办法必须定义在构造函数中,所以会导致每次创立子类实例都会创立一遍办法。

组合继承

组合继承联合了原型链和盗用构造函数,将两者的长处集中了起来。根本的思路是应用原型链继承原型上的属性和办法,而通过盗用构造函数继承实例属性。这样既能够把办法定义在原型上以实现重用,又能够让每个实例都有本人的属性。

function Animal(name) {    this.name = name    this.colors = ['black', 'white']}Animal.prototype.getName = function() {    return this.name}function Dog(name, age) {    Animal.call(this, name)    this.age = age}Dog.prototype =  new Animal()Dog.prototype.constructor = Doglet dog1 = new Dog('奶昔', 2)dog1.colors.push('brown')let dog2 = new Dog('哈赤', 1)console.log(dog2) // { name: "哈赤", colors: ["black", "white"], age: 1 }

寄生式组合继承

组合继承曾经绝对欠缺了,但还是存在问题,它的问题就是调用了 2 次父类构造函数,第一次是在 new Animal(),第二次是在 Animal.call() 这里。

所以解决方案就是不间接调用父类构造函数给子类原型赋值,而是通过创立空函数 F 获取父类原型的正本。

寄生式组合继承写法上和组合继承根本相似,区别是如下这里:

- Dog.prototype =  new Animal()- Dog.prototype.constructor = Dog+ function F() {}+ F.prototype = Animal.prototype+ let f = new F()+ f.constructor = Dog+ Dog.prototype = f

略微封装下下面增加的代码后:

function object(o) {    function F() {}    F.prototype = o    return new F()}function inheritPrototype(child, parent) {    let prototype = object(parent.prototype)    prototype.constructor = child    child.prototype = prototype}inheritPrototype(Dog, Animal)

如果你厌弃下面的代码太多了,还能够基于组合继承的代码改成最简略的寄生式组合继承:

- Dog.prototype =  new Animal()- Dog.prototype.constructor = Dog+ Dog.prototype =  Object.create(Animal.prototype)+ Dog.prototype.constructor = Dog

class 实现继承

class Animal {    constructor(name) {        this.name = name    }     getName() {        return this.name    }}class Dog extends Animal {    constructor(name, age) {        super(name)        this.age = age    }}

对 rest 参数的了解

扩大运算符被用在函数形参上时,它还能够把一个拆散的参数序列整合成一个数组

function mutiple(...args) {  let result = 1;  for (var val of args) {    result *= val;  }  return result;}mutiple(1, 2, 3, 4) // 24

这里,传入 mutiple 的是四个拆散的参数,然而如果在 mutiple 函数里尝试输入 args 的值,会发现它是一个数组:

function mutiple(...args) {  console.log(args)}mutiple(1, 2, 3, 4) // [1, 2, 3, 4]

这就是 … rest运算符的又一层威力了,它能够把函数的多个入参收敛进一个数组里。这一点常常用于获取函数的多余参数,或者像下面这样解决函数参数个数不确定的状况。

怎么加事件监听,两种

onclick 和 addEventListener

伪元素和伪类的区别和作用?

  • 伪元素:在内容元素的前后插入额定的元素或款式,然而这些元素实际上并不在文档中生成。它们只在内部显示可见,但不会在文档的源代码中找到它们,因而,称为“伪”元素。例如:
p::before {content:"第一章:";}p::after {content:"Hot!";}p::first-line {background:red;}p::first-letter {font-size:30px;}
  • 伪类:将非凡的成果增加到特定选择器上。它是已有元素上增加类别的,不会产生新的元素。例如:
a:hover {color: #FF00FF}p:first-child {color: red}

总结: 伪类是通过在元素选择器上加⼊伪类扭转元素状态,⽽伪元素通过对元素的操作进⾏对元素的扭转。

同步和异步的区别

  • 同步指的是当一个过程在执行某个申请时,如果这个申请须要期待一段时间能力返回,那么这个过程会始终期待上来,直到音讯返回为止再持续向下执行。
  • 异步指的是当一个过程在执行某个申请时,如果这个申请须要期待一段时间能力返回,这个时候过程会持续往下执行,不会阻塞期待音讯的返回,当音讯返回时零碎再告诉过程进行解决。

大数相加

题目形容:实现一个add办法实现两个大数相加

let a = "9007199254740991";let b = "1234567899999999999";function add(a ,b){   //...}

实现代码如下:

function add(a ,b){   //取两个数字的最大长度   let maxLength = Math.max(a.length, b.length);   //用0去补齐长度   a = a.padStart(maxLength , 0);//"0009007199254740991"   b = b.padStart(maxLength , 0);//"1234567899999999999"   //定义加法过程中须要用到的变量   let t = 0;   let f = 0;   //"进位"   let sum = "";   for(let i=maxLength-1 ; i>=0 ; i--){      t = parseInt(a[i]) + parseInt(b[i]) + f;      f = Math.floor(t/10);      sum = t%10 + sum;   }   if(f!==0){      sum = '' + f + sum;   }   return sum;}

对 sticky 定位的了解

sticky 英文字面意思是粘贴,所以能够把它称之为粘性定位。语法:position: sticky; 基于用户的滚动地位来定位。

粘性定位的元素是依赖于用户的滚动,在 position:relativeposition:fixed 定位之间切换。它的行为就像 position:relative; 而当页面滚动超出指标区域时,它的体现就像 position:fixed;,它会固定在指标地位。元素定位体现为在逾越特定阈值前为绝对定位,之后为固定定位。这个特定阈值指的是 top, right, bottom 或 left 之一,换言之,指定 top, right, bottom 或 left 四个阈值其中之一,才可使粘性定位失效。否则其行为与绝对定位雷同。

对类数组对象的了解,如何转化为数组

一个领有 length 属性和若干索引属性的对象就能够被称为类数组对象,类数组对象和数组相似,然而不能调用数组的办法。常见的类数组对象有 arguments 和 DOM 办法的返回后果,函数参数也能够被看作是类数组对象,因为它含有 length属性值,代表可接管的参数个数。

常见的类数组转换为数组的办法有这样几种:

  • 通过 call 调用数组的 slice 办法来实现转换
Array.prototype.slice.call(arrayLike);
  • 通过 call 调用数组的 splice 办法来实现转换
Array.prototype.splice.call(arrayLike, 0);
  • 通过 apply 调用数组的 concat 办法来实现转换
Array.prototype.concat.apply([], arrayLike);
  • 通过 Array.from 办法来实现转换
Array.from(arrayLike);

数组的遍历办法有哪些

办法是否扭转原数组特点
forEach()数组办法,不扭转原数组,没有返回值
map()数组办法,不扭转原数组,有返回值,可链式调用
filter()数组办法,过滤数组,返回蕴含符合条件的元素的数组,可链式调用
for...offor...of遍历具备Iterator迭代器的对象的属性,返回的是数组的元素、对象的属性值,不能遍历一般的obj对象,将异步循环变成同步循环
every() 和 some()数组办法,some()只有有一个是true,便返回true;而every()只有有一个是false,便返回false.
find() 和 findIndex()数组办法,find()返回的是第一个符合条件的值;findIndex()返回的是第一个返回条件的值的索引值
reduce() 和 reduceRight()数组办法,reduce()对数组正序操作;reduceRight()对数组逆序操作

OPTIONS申请办法及应用场景

OPTIONS是除了GET和POST之外的其中一种 HTTP申请办法。

OPTIONS办法是用于申请取得由Request-URI标识的资源在申请/响应的通信过程中能够应用的性能选项。通过这个办法,客户端能够在采取具体资源申请之前,决定对该资源采取何种必要措施,或者理解服务器的性能。该申请办法的响应不能缓存。

OPTIONS申请办法的主要用途有两个:

  • 获取服务器反对的所有HTTP申请办法;
  • 用来查看拜访权限。例如:在进行 CORS 跨域资源共享时,对于简单申请,就是应用 OPTIONS 办法发送嗅探申请,以判断是否有对指定资源的拜访权限。

什么是 CSRF 攻打?

(1)概念

CSRF 攻打指的是跨站申请伪造攻打,攻击者诱导用户进入一个第三方网站,而后该网站向被攻打网站发送跨站申请。如果用户在被攻打网站中保留了登录状态,那么攻击者就能够利用这个登录状态,绕过后盾的用户验证,假冒用户向服务器执行一些操作。

CSRF 攻打的实质是利用 cookie 会在同源申请中携带发送给服务器的特点,以此来实现用户的假冒。

(2)攻打类型

常见的 CSRF 攻打有三种:

  • GET 类型的 CSRF 攻打,比方在网站中的一个 img 标签里构建一个申请,当用户关上这个网站的时候就会主动发动提交。
  • POST 类型的 CSRF 攻打,比方构建一个表单,而后暗藏它,当用户进入页面时,主动提交这个表单。
  • 链接类型的 CSRF 攻打,比方在 a 标签的 href 属性里构建一个申请,而后诱导用户去点击。

对Flex布局的了解及其应用场景

Flex是FlexibleBox的缩写,意为"弹性布局",用来为盒状模型提供最大的灵活性。任何一个容器都能够指定为Flex布局。行内元素也能够应用Flex布局。留神,设为Flex布局当前,子元素的float、clear和vertical-align属性将生效。采纳Flex布局的元素,称为Flex容器(flex container),简称"容器"。它的所有子元素主动成为容器成员,称为Flex我的项目(flex item),简称"我的项目"。容器默认存在两根轴:程度的主轴(main axis)和垂直的穿插轴(cross axis),我的项目默认沿程度主轴排列。

以下6个属性设置在容器上

  • flex-direction属性决定主轴的方向(即我的项目的排列方向)。
  • flex-wrap属性定义,如果一条轴线排不下,如何换行。
  • flex-flow属性是flex-direction属性和flex-wrap属性的简写模式,默认值为row nowrap。
  • justify-content属性定义了我的项目在主轴上的对齐形式。
  • align-items属性定义我的项目在穿插轴上如何对齐。
  • align-content属性定义了多根轴线的对齐形式。如果我的项目只有一根轴线,该属性不起作用。

以下6个属性设置在我的项目上

  • order属性定义我的项目的排列程序。数值越小,排列越靠前,默认为0。
  • flex-grow属性定义我的项目的放大比例,默认为0,即如果存在残余空间,也不放大。
  • flex-shrink属性定义了我的项目的放大比例,默认为1,即如果空间有余,该我的项目将放大。
  • flex-basis属性定义了在调配多余空间之前,我的项目占据的主轴空间。浏览器依据这个属性,计算主轴是否有多余空间。它的默认值为auto,即我的项目的原本大小。
  • flex属性是flex-grow,flex-shrink和flex-basis的简写,默认值为0 1 auto。
  • align-self属性容许单个我的项目有与其余我的项目不一样的对齐形式,可笼罩align-items属性。默认值为auto,示意继承父元素的align-items属性,如果没有父元素,则等同于stretch。

简略来说: flex布局是CSS3新增的一种布局形式,能够通过将一个元素的display属性值设置为flex从而使它成为一个flex容器,它的所有子元素都会成为它的我的项目。一个容器默认有两条轴:一个是程度的主轴,一个是与主轴垂直的穿插轴。能够应用flex-direction来指定主轴的方向。能够应用justify-content来指定元素在主轴上的排列形式,应用align-items来指定元素在穿插轴上的排列形式。还能够应用flex-wrap来规定当一行排列不下时的换行形式。对于容器中的我的项目,能够应用order属性来指定我的项目的排列程序,还能够应用flex-grow来指定当排列空间有残余的时候,我的项目的放大比例,还能够应用flex-shrink来指定当排列空间有余时,我的项目的放大比例。

代码输入后果

function SuperType(){    this.property = true;}SuperType.prototype.getSuperValue = function(){    return this.property;};function SubType(){    this.subproperty = false;}SubType.prototype = new SuperType();SubType.prototype.getSubValue = function (){    return this.subproperty;};var instance = new SubType();console.log(instance.getSuperValue());

输入后果:true

实际上,这段代码就是在实现原型链继承,SubType继承了SuperType,实质是重写了SubType的原型对象,代之以一个新类型的实例。SubType的原型被重写了,所以instance.constructor指向的是SuperType。具体如下:

字符串模板

function render(template, data) {    const reg = /\{\{(\w+)\}\}/; // 模板字符串正则    if (reg.test(template)) { // 判断模板里是否有模板字符串        const name = reg.exec(template)[1]; // 查找以后模板里第一个模板字符串的字段        template = template.replace(reg, data[name]); // 将第一个模板字符串渲染        return render(template, data); // 递归的渲染并返回渲染后的构造    }    return template; // 如果模板没有模板字符串间接返回}

测试:

let template = '我是{{name}},年龄{{age}},性别{{sex}}';let person = {    name: '布兰',    age: 12}render(template, person); // 我是布兰,年龄12,性别undefined

如果new一个箭头函数的会怎么样

箭头函数是ES6中的提出来的,它没有prototype,也没有本人的this指向,更不能够应用arguments参数,所以不能New一个箭头函数。

new操作符的实现步骤如下:

  1. 创立一个对象
  2. 将构造函数的作用域赋给新对象(也就是将对象的__proto__属性指向构造函数的prototype属性)
  3. 指向构造函数中的代码,构造函数中的this指向该对象(也就是为这个对象增加属性和办法)
  4. 返回新的对象

所以,下面的第二、三步,箭头函数都是没有方法执行的。

map和Object的区别

MapObject
意外的键Map默认状况不蕴含任何键,只蕴含显式插入的键。Object 有一个原型, 原型链上的键名有可能和本人在对象上的设置的键名产生抵触。
键的类型Map的键能够是任意值,包含函数、对象或任意根本类型。Object 的键必须是 String 或是Symbol。
键的程序Map 中的 key 是有序的。因而,当迭代的时候, Map 对象以插入的程序返回键值。Object 的键是无序的
SizeMap 的键值对个数能够轻易地通过size 属性获取Object 的键值对个数只能手动计算
迭代Map 是 iterable 的,所以能够间接被迭代。迭代Object须要以某种形式获取它的键而后能力迭代。
性能在频繁增删键值对的场景下体现更好。在频繁增加和删除键值对的场景下未作出优化。

forEach和map办法有什么区别

这办法都是用来遍历数组的,两者区别如下:

  • forEach()办法会针对每一个元素执行提供的函数,对数据的操作会扭转原数组,该办法没有返回值;
  • map()办法不会扭转原数组的值,返回一个新数组,新数组中的值为原数组调用函数解决之后的值;

数组去重

ES5 实现:

function unique(arr) {    var res = arr.filter(function(item, index, array) {        return array.indexOf(item) === index    })    return res}

ES6 实现:

var unique = arr => [...new Set(arr)]