js基础知识点及常见的面试题(一)

基本类型(Primitive)

面试题 基本类型有哪几种?null是对象吗?

js基本类型

boolean

null

undefined

number

string

symbol

基本类型存储的都是值,是没有函数可以调用的,比如undefined.toString(),你可能会有疑问,'1'.toString()是可以使用的,'1'已经不是基本类型了,而是被强制转化成了String类型,也就是对象类型,所以可以调用toString函数。

除了会在必要的情况下强转类型意外,原始类型还有一些坑。

其中js的number浮点类型的,在使用过程中遇到某些bug,比如0.1+0.2 !== 0.3 返回的是false,string类型是不可变的,无论你在string类型上调用任何方法,都不会对值有改变。

另外对于null来说,很多认为它是一个对象类型,这是不对的,虽然typeof 返回的是object,但它只是js中一直存在的bug,js最初的版本是32位系统,为了性能的考虑使用低位存储变量的类型信息,000开头的是对象,然而null表示为全零,所以将他错误的判断为对象,虽然现在内部类型的代码已经改变,但对于这个bug一直保存了下来。

对象类型

面试题 对象类型和基本类型的不同指出?函数参数是对象会发生什么问题?

在js中,除了基本类型就是对象类型了,对象类型和基本类型不同的是,基本类型存储的是值,对象类型存储的是指针,当你创建一个对象类型的时候,计算机内存会帮我们开辟一个空间来存放值,但我们需要找到这个空间,这个空间会拥有一个指针。

const a = []

对于常量a来说,假设地址为#0001,在该地址存储了[],常量地址存储了地址#0001,再看以下代码

const a = []

const b = a

console.log(b)

当我们将变量赋给另一个变量时,复制的是原本变量的指针,当我们修改存放的地址的值,也导致了两个变量的值发生了改变。

接下来我们看下函数参数是对象的情况

function test(person){

    person.age =26

    person ={

        name:'han',

        age:30

    }

    return person

}

const p1 = {

    name:'xiao',

    age:'34'

}

const p2 = test(p1)

console.log(p1)

console.log(p2)

对于以上代码你能否写出正确的结果,接下来我们来分析一下

首先函数传参是传递的指针副本

到函数内部修改参数这步,当前p1的值也被修改了

当我们重新为person分配一个对象时,就产生了分歧

所以person有了一个新的指针,也就和p1没什么关系了,导致了最后两个变量的值时不同的

typeof vs instanceof

面试题 typeof能否正确判断类型?instanceof正确对象的原理是什么? typeof对于原始类型来说,除了null都可以显示正确的类型。

typeof 1 // number

typeof '1' //string

typeof undefined // 'undefined'

typeof true // 'boolean'

typeof Symbol() // 'symbol'

typeof 对于对象来说,除了函数都会显示 object,所以说 typeof 并不能准确判断变量到底是什么类型

typeof [] // 'object'

typeof {} // 'object'

typeof console.log // 'function'

如果我们想判断一个对象的正确类型,这时候我们要考虑使用instanceof,因为内部机制时通过原型链进行判断的

const Person = function(){


}

const p1 = new Person()

p1 instanceof Person

var str ='person'

str instanceof String

var str1 = new String('xiao')

str1 instanceof str1

对于基本类型来说,你通过instanceof来判断类型是不行的,当然我们是有办法让instanceof判断基本类型的

class PrimitiveString {

  static [Symbol.hasInstance](x) {

    return typeof x === 'string'

  }

}

console.log('hello world' instanceof PrimitiveString) // true

你可能不知道 Symbol.hasInstance 是什么东西,其实就是一个能让我们自定义 instanceof 行为的东西,以上代码等同于 typeof 'hello world' === 'string',所以结果自然是 true 了。这其实也侧面反映了一个问题, instanceof 也不是百分之百可信的。

类型转换

首先我们知道js中类型转换只有三种情况:

转换为布尔值

转换为数字

转换为字符串

我们先看一下下面的例子

原始值                      转化目标            结果

number                      布尔值          除了0,-0,NaN都为true

string                      布尔值          除了字符串都为true

undefined null              布尔值          false

引用类型                    布尔值          true

number                      字符串          5=>'5' 

布尔 函数 symbol            字符串          'true'

数组                        字符串          [1,2]=>1,2

对象                        字符串          "[object object]"

字符串                      数字            '1'=>1,'a'=>NaN

数组                        数字            空数组转化为0,有一个元素且为数字

                                            转化为数字,其他情况则为NaN

null                        数字            0

除了数组的引用类型          数字            NaN

symbol                      数字            报错

转boolean

在条件判断时,除了undefined,null,false,NaN,'',0,-0,其他所有的值都为true,包括所有对象

对象转换原始类型 对象在转换类型的时候,会调用内置的[[ToPrimitive]]函数,对于该函数来说,算法逻辑一般如下:

如果已经时原始类型了,那就不需要转换了

如果需要转字符串类型就调用x.toString(),转换为基础类型的话就返回转换的值。不转换字符串类型的话就先调用valueof,结果不是基础类型的话再调用tostring

调用x.valueof(),如果转换为基础类型,就返回转换的值

如果没有返回原始类型,就会报错

当然你也可以重写Symbol.toPrimitive,该方法在转原始类型时调用优先级最高

let a={

    valueof(){

        return 0

    },

    toString(){

        return 1

    },

    [].toPrimitive(){

        return 2

    }

}

1+a //3

四则运算符

加法运算符不同于其他几个运算符,它有以下特点

运算中其中一方为字符串,那么就会把另一方转化为字符串

如果一方不是字符串或者数字,那么会将数字转化为字符串

1+'1' //1

true+true //2

4+[1,2,3] //41,2,3

如果对于答案有疑问的话,请看解析:

对于第一行代码来说,触发特点一,所以将数字以1转化为字符串,结果得到‘11’

对于第二行代码来说,触发特点二,所以将true转为数字1

对于第三行代码来说,触发特点二,将数组通过toString转化为字符串1,2,3,得到结果41,2,3

另外对于加法还需要主义这个表达式

'a'++'b' //"aNaN"

应为+'b'等于NaN,所以结果为“NaN”,你可能也会在一些代码中看到过+‘1’的形式来快速获取number类型 对了除了加法的运算符来说,只要其中一方时数字,那么另一方就会转化为数字

4*'3' //12

4*[] //0

4*[1,2] //NaN

比较运算符

1.如果是对象,就通过toPrimitive转化对象 2.如果是字符串,就通过unicode字符索引比较

let a={

    valueof(){

        return 0

    },

    toString(){

        return '1'

    }

}

a>-1 //true

在以上代码中,因为a是对象,所以会通过valueof转换为原始类型再比较

this

面试题 如何正确判断this?箭头函数this是什么? this是很多人混淆的概念,但是其实它一点都不难,只是网上很多文章把简单的东西说的复杂了,在这一小节中,你一定会彻底明白this这个概念的

function foo(){

    console.log(this.a)

}

var a=1

foo()

const obj = {

    a:2,

    foo:foo

}

obj.foo()

const c = new foo()

接下来我们一个个分析上面几个场景

对于直接调用foo来说,不管函数被放在什么地方,this一定是window

对于obj.foo()来说,我们只需记住,谁调用了函数,谁就是this,所以在这个场景下foo函数中的this就是obj

对于new方式来说,this永远绑定在了c上面,不会被任何方式改变this

首先箭头函数其实没有this的,箭头函数中的this只取决包裹箭头函数的第一个普通函数的 this

function a(){

    return ()=>{

        return ()=>{

            return this

        }

    }

}

console.log(a()())

说完了上面的几种情况,其实很多代码中的this应该没什么问题了,下面我们看看箭头函数中的this,在这个例子中,因为包裹箭头函数的第一个普通函数是a,所以此时的this是window。另外对箭头函数使用bind,apply,call这类函数是无效的。

最后情况也就是bind这些改变上下文的api了,对于这些函数来说,this取决于第一个参数,如果第一个参数为空,那么就是window

那么说到bind,如果对一个函数进行多次bind,那么上下文会是什么呢?

let a ={}

let fn = function(){

    console.log(this)

}

fn.bind().bind(a)()

如果你认为输出的结果是a,那么就错了,其实我们可以换成另一种形式

//fn.bind().bind(a)等于

let fn2 = function(){

    return function(){

        return fn.apply()

    }

}

fn2()

可以从上述代码中发现,不管我们给函数bind几次,fn中的this永远由第一次bind决定,所以结果永远是window

let a = {

    name:'han'

}

function foo(){

    console.log(this.name)

}

foo.bind(a)()  //han

以上就是this的规则了,但是可能会发生多个规则同时出现的情况,这时候不同的规则之间会根据优先级最高的来决定this最终指向哪里。

首先,new的优先级方式最高,接下来是bind这些函数了,然后obj.foo()这种调用方式,最后foo这种调用方式,同时,箭头函数的this一旦绑定,就不会再被任何方式有所改变

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,723评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,003评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,512评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,825评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,874评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,841评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,812评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,582评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,033评论 1 308
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,309评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,450评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,158评论 5 341
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,789评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,409评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,609评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,440评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,357评论 2 352