js原生面试题

一、es6中的箭头函数和普通函数有什么区别?

1、普通函数中的 this总是指向调用它的那个对象,

箭头函数没有自己的this,他的this永远指向其定义环境,任何方法都改变不了其指向,如call()、bind()、apply()。(正是因为它没有this,所以也就不能用作构造函数,也没有原型对象)

箭头函数不能当作构造函数,也就是说,不能使用new命令,否则会报错。

箭头函数没有原型属性。

箭头函数不可以使用yield命令,因此箭头函数不能用作Generator函数。

箭头函数不能使用arguments对象,该对象在函数体内不存在。如果要用,可以用rest参数代替。

变量提升:由于js的内存机制,function的级别最高,而用箭头函数定义函数的时候,需要var(let、const)关键字,而var所定义的变量不能得到变量提升。故箭头函数一定要定义于调用之前。

拓展:this的指向问题?

    1、普通函数中,this指向其函数的直接调用者;

    2、箭头函数中,this指向其定义环境,任何方法都改变不了其指向,如call( )、bind()等;

    3、构造函数中,如果不使用new,则this指向window,

        如果使用new创建了一个实例,则this指向该实例。

  4、window内置函数中,如setInterval,setTimeout等,其内部的this指向Window。

    5、匿名函数的this指向Window。

    6、apply()、call()、bind()可以改变this的指向


二、谈谈你对原型链的认识?

https://blog.csdn.net/xiaotao_css/article/details/72782416:通俗易懂的介绍(仅供18岁以上成年阅读)

看下面的东西之前,建议先看上面链接的这篇文章

    对象: 1 、 函数对象: 由 function 创造出来的函数,比如 function a(){ } ; 系统内置的函数对象: Function , Object , Array , String , Number


                2、 普通对象: 除开函数对象之外的对象,都是普通对象

               每个普通对象的__proto__属性,都指向Object().prototype ,

                var obj = { }  就等于  var obj = new Object ( ) ;  即普通对象是  构造函数( Object ) 的一个实例

                所以  obj. __proto__    ===  Object.prototype  ( 但是老高说的,Object的原型还是object对象, )

                          obj. constructor  ===  Object 

    凡是通过 new Function() 创建的对象都是函数对象,其他的都是普通对象。

    注:所有对象都有 __proto__ 属性只有函数对象才有 prototype 属性 !!!!!!!!!!!

    原型对象: prototype 属性也叫原型对象,主要是为了实现继承;


     指针 __proto__ :  js中,万物皆对象!所有的对象 obj 都具有 proto 属性(null 和 undefined除外 ),而且指向创造obj 对象的函数对象(生成实例的构造函数)的prototype属性 。 如以下例子:


Person 构造函数的原型对象 是 Mother ()。相当于原型是妈妈,Person现在是儿子。

在 p1 和 p2 实例中,__proto__属性,指向的是 创造他们的构造函数Person 对象的 prototype 属性,所对应的对象。

也就是 Mother().

一个构造函数对象的原型,就相当于 他妈,这个构造函数对象的实例,就相当于  他妈不同的孩子。

而 每个 实例中的 __proto__属性,就指向 他们共同的 妈 !也就是 构造函数对象的 prototype属性。

当我们输入 p1.name 的时候,原型链的搜索机制是先在实例中搜索相应的值,找不到就通过它的__proto__指针,在原型中找,还找不到就再往上一级原型中搜索……一直到了原型链的终点( 就是js自带的Object,它的原型比较特殊,为null ),就是到null还没找到的话,就返回一个 undefined。

    构造器constructor : 每一个对象中的constructor 属性返回创建此对象的函数对象的引用;例如:

     functon  Dog ( name, color ) { 

        this. name = name;

        this. color = color;

    }

    var dog1 = new Dog( "小白" , "白色" );

    dog1.constructor == Dog 构造函数本身

在默认情况下,所有的原型对象都会自动获得一个 constructor(构造函数)属性,这个属性(是一个指针)指向 prototype 属性所在的函数(Person)

上面这句话有点拗口,我们「翻译」一下:A 有一个默认的 constructor 属性,这个属性是一个指针,指向 Person。即:

Person.prototype.constructor == Person

实例的构造函数属性(constructor)指向构造函数 :person1.constructor == Person

person1 为什么有 constructor 属性?那是因为 person1 是 Person 的实例。

那 Person.prototype 为什么有 constructor 属性??同理, Person.prototype (你把它想象成 A) 也是Person 的实例。

也就是在 Person 创建的时候,创建了一个它的实例对象并赋值给它的 prototype,基本过程如下:

var A = new Person();

Person.prototype = A;

结论:原型对象(Person.prototype)是 构造函数(Person)的一个实例。

以下代码的图示 

            function Foo ( ) { } ;

var f1 = new Foo;

以下是 深入解答原型是怎么回事 的一篇文章 

1、https://www.jianshu.com/p/dee9f8b14771

2、https://www.jianshu.com/p/652991a67186

3、https://www.jianshu.com/p/a4e1e7b6f4f8    

原型链的概念

如果问原型链是什么,直接把下面的这张图画出来就行了。

https://www.cnblogs.com/shuiyi/p/5305435.html

腾讯大学原生JS 视频 :https://ke.qq.com/course/231577

回答出以下问题,就知道 __proto__和prototype 的什么了

function Person(){   } ;

var person1 = new Person( );

person1.__proto__ 是什么?

Person.__proto__ 是什么?

Person.prototype.__proto__ 是什么?

Object.__proto__ 是什么?

Object.prototype__proto__ 是什么?

答案:

第一题:

因为 person1.__proto__ === person1 的构造函数.prototype

因为 person1的构造函数 === Person

所以person1.__proto__ === Person.prototype

第二题:

因为 Person.__proto__ === Person的构造函数.prototype

因为 Person的构造函数 === Function

所以Person.__proto__ === Function.prototype

第三题:

Person.prototype 是一个普通对象,我们无需关注它有哪些属性,只要记住它是一个普通对象。

因为一个普通对象的构造函数 === Object

所以Person.prototype.__proto__ === Object.prototype

第四题,参照第二题,因为 Person 和 Object 一样都是构造函数

               不要把 Object 想的太复杂,它其实也不过是 Function 构造出来的一个 方法 (一个普通的构造函数)

                所以 Object.__proto__ === Function.prototype

第五题:

Object.prototype 对象也有proto属性,但它比较特殊,为 null 。因为 null 处于原型链的顶端,这个只能记住。

Object.prototype.__proto__ === null

记住:prototype是一个普通对象,所有普通对象的__protp__都指向 Object.prototype

三、js跨域问题怎么解决?

   1、 JSONP跨域请求

    要理解跨域,先要了解一下”同源策略“。所谓同源是指,协议、域名、端口都相同。所谓”同源策略“,简单的说,就是基于安全考虑,当前域不能访问其他域的东西。

http 和 https :协议不同

www.a.com 和www.b.com :域名不同

www.a.com : 8080 和www.a.com : 1000   :   端口不同

在同源策略下,在某个服务器下的页面是无法获取到该服务器以外的数据的。

例如我们在自己的网站通过 ajax 去 获取豆瓣上的图书接口:

https://api.douban.com/v2/book/search?q=javascript&count=1

我们通过以上 ajax 去访问,发现运行时会报错:

只要出现这个错误,就说明服务器接口不支持跨域

//No 'Access-Control-Allow-Origin' header is present on the requested resource

这是因为不同源,所以无法访问其他服务器的数据

但是<img> 的 src ( 获取图片 ) ,  <link> 的 href (获取css),<script> 的 src (获取js)这三个属性都不符合同源策略,它们可以跨域获取数据。JSONP就是利用<script> 的 src 来实现跨域获取数据。

跨域原理

    JSONP实现跨域请求的原理,简单的说,就说动态创建 <script>标签,然后利用<script>的 src 不受同源策略的约束来跨域获取数据。

    JSONP 由两部分组成:回调函数和数据。回调函数 是当响应到来时,应该在页面中调用的函数。回调函数的名字,一般是在请求中指定的。而数据就是传入回调函数中的 JSON 数据。

注意:JSONP不是真正的 ajax 

ajax是异步的,jsonp是同步的,所以它不是真正的ajax

动态创建 <script> 标签,设置其 src ,回调函数在 src 中设置:

var script = document.createElement("script");

script.src = "https://api.douban.com/v2/book/search?q=javascript&count=1";

document.body.insertBefore( script, document.body.firstChild );

在页面中,返回的 JSON 作为参数传入 回调函数中,我们通过回调函数来 操作数据

function handleResponse(response){

    //对 response 数据进行操作代码

}

 了解了 JSONP 的基本使用方法,我们在实现上面,通过 ajax 调用豆瓣接口的需求,实现代码如下:

注意:以上代码中,要记得成功访问完数据后,要删除创建的动态 <script>标签:

document.body.removeChild(script)

其实在接口数据的形式类似:fn( { name: "张三" , age: "20" } ) ,我们传递过去一个和这个函数名字相同的回调函数,参数就是访问到的数据。

假如接口是:http://api.money.126.net/data/feed/0000001,1399001?callback=refreshPrice

函数名就是 callbanck = 的值:refreshPrice.

JSONP目前还是比较流行的跨域方式,虽然JSONP使用起来方便,但是也存在一些问题:如果其他域不安全,很可能会在响应中夹带一些恶意代码。而且要确定 JSONP请求是否失败并不容易。

JSONP有个限制,只能用GET请求,并且要求返回JavaScript

更多跨域的方法介绍:

https://www.liaoxuefeng.com/wiki/001434446689867b27157e896e74d51a89c25cc8b43bdb3000/001434499861493e7c35be5e0864769a2c06afb4754acc6000

对axios有更进一步的理解,利用cros进行跨域处理!!!

2、CROS跨域

3、反向代理

四、闭包

    概念: 闭包就是能够读取其他函数内部变量的函数。

    由于函数内部的子函数才能读取局部变量,因此可以把闭包简单理解成“定义在一个函数内部的函数”(然后将这个内部的函数 return 返回出来)。

    所以,在本质上,闭包就是将函数内部和函数外部连接起来的一座桥梁。

    闭包的作用:它最大的用处有两个: 1) 一个是可以读取函数内部的变量;

                                                           2) 另一个就是让这些变量的值始终保存在内存中。

    使用闭包的注意点:1) 由于闭包会使得函数中的变量都保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,在IE中可能导致内存泄漏。解决方法是,在退出函数之前,将不使用的局部变量全部删除。

                                    内存泄漏:程序的运行需要内存。对于持续运行的服务进程,必须及时释放不再用到的内存,否则占用越来越高,轻则影响系统性能,重则导致进程崩溃。不再用到的内存,没有及时释放,就叫做内存泄漏。

http://www.ruanyifeng.com/blog/2017/04/memory-leak.html


                                   2) 闭包会在父函数外部,改变父函数内部变量的值。所以,如果你把父函数当作对象(object)使用,把闭包当作它的公用方法,把内部变量当作它的私有属性,这时一定要小心,不要随便改变父函数内部变量的值。

五、promise的用法和原理?

基础https://mengera88.github.io/2017/05/15/promise%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/

原理

https://segmentfault.com/a/1190000009478377

 概念:promise 是异步编程的一种解决方案。它可以把异步操作以同步操作的流程表达出来,避免了层层嵌套的回调函数。

 Promise 为异步操作提供了统一的接口,使得控制异步操作更加容易,它的强大之处在于它的链式调用。

基本用法:


newPromise(function(resolve, reject){

//待处理的异步逻辑

//处理结束后,调用resolve或reject方法

})

新建一个promise很简单,只需要new 一个 Promise 对象即可。所以promise本质上就是一个函数,它接受一个函数作为参数,并且返回promise对象,这就给链式调用提供了基础。

特点:

1、对象的状态不受外界影响。

Promise 的实例 有以下三种状态:

    1)pending : 进行中

    2)resolved : 已成功完成

    3)rejected : 已失败

只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。

2、一旦状态改变,就不会再变,任何时候都可以得到这个结果。Promise对象的状态改变,只有两种可能:从pending变为resolved;从pending变为rejected。 只要这两种情况发生,状态就凝固了,不会再变了,会一直保持这个结果。

基本用法:

ES6规定,Promise 对象是一个构造函数,用来生成Promise实例

Promise构造函数接受一个函数作为参数,该函数的两个参数分别是resolve和reject。它们是两个函数,由JavaScript 引擎提供, 不是自己部署。

resolve函数的作用,将Promise对象的状态从“进行中”变成 “成功”( 即从pending变为resolved ) ,在异步操作成功时调用,并将异步操作的结果,作为参数传递出去。

reject函数的作用,在异步操作失败时调用,并将异步操作报出的错误,作为参数传递出去。

Promise实例生成以后,可以用then方法分别制定 Resolved状态和Rejected状态的回调函数:

then方法可以接受 2 个回调函数作为参数,第二个函数是可选的,不一定要提供。这两个函数都接受Promise对象传出的值作为参数。

promise捕获错误  .catch方法:


Promise.prototype.catch方法是Promise.prototype.then(null, rejection)的别名,用于指定发生错误时的回调函数。

Promise对象的错误具有“ 冒泡 ”性质,会一直向后传递,直到被捕获为止。也就是说,错误总是会被下一个catch语句捕获。

题外话:async 函数是es7 提案出来的语法, async函数是用来取代回调函数的另一种方法。

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

推荐阅读更多精彩内容