JavaScript基础--------三座大山(前端面试必考)

1.原型和原型链

2.作用域和闭包

3.异步和单线程

被称为JavaScript的三座大山

原型和原型链:

在JavaScript中,数组,对象和函数被称为引用类型,他们都有一个__proto__属性,该属性是一个对象(我们称之为隐式原型)

arr数组的构造函数是Array,Array构造函数中有一个prototype属性,(我们暂时称之为显式原型)

arr是构造函数的实例对象,arr中的__proto__对象指向构造函数中的prototype对象

接下来是一个简单的demo

 1 //创建一个构造函数
 2         function Animal(name){
 3             this.name = name
 4         }
 5         Animal.prototype.eat = function(){
 6             console.log(‘Animal--eat‘)
 7         }
 8         // 用new初始化一个Animal的实例对象
 9         var dog = new Animal(‘xiaohuang‘)
10
11         console.log(dog.name)
12         console.log(dog.eat())

输出结果为

看一下dog对象中有什么属性

调用dog的属性和方法时,会先从dog本身去查找,如果dog本身没有那个属性或方法,就会去dog的__proto__原型中去查找,而__proto__又指向Animal的prototype(看第二个constructor对象,指向Animal),这就是原型链

再来一个demo

 1 //创建一个构造函数
 2         function Animal(name){
 3             this.name = name
 4         }
 5         //创建一个Hashiqi的构造函数
 6         function Hashiqi(){
 7         }
 8         Animal.prototype.eat = function(){
 9             console.log(‘Animal--eat‘)
10         }
11         Hashiqi.prototype.color = function(){
12             console.log(‘Hashiqi---color‘)
13         }
14         //改变prototype的指向
15         Animal.prototype = new Hashiqi()
16         // 用new初始化一个Animal的实例对象
17         var dog = new Animal(‘xiaohuang‘)
18
19         console.log(dog.name)
20         console.log(dog.eat())
21         console.log(dog.color())

这个demo中改变了Animal的prototype,将其指向一个Hashiqi的实例对象,我们来看结果。此时dog.eat()会报错,dog.color正常输出

第三个demo,比较上档次一点

 1 <div id="wrapper">this is wrapper</div>
 2     <script>
 3         //创建一个Elem的构造函数
 4        function Elem(id){
 5            //获取dom元素
 6            this.id = document.getElementById(id)
 7        }
 8        Elem.prototype.html = function(val){
 9            //如果val为空,则打印dom元素的innerhtml值
10            if(val == null){
11                console.log(this.id.innerHTML)
12                //返回this,可以用来进行链式操作
13                return this
14            }else{
15                this.id.innerHTML = val
16                return this
17            }
18        }
19        //绑定事件
20        Elem.prototype.on = function(type, fn){
21            this.id.addEventListener(type,fn)
22        }
23
24     </script>

首先new一个实例对象:  var el = new Elem(‘wrapper‘)

            el.html(‘ ookook ‘).on(‘click‘, function(){  console.log(‘this is ook‘) }  )

接下来点击ookook就会打印this is ook

 作用域和闭包:

JavaScript中有函数作用域和全局作用域(es6中用let声明的变量具有块作用域)

函数作用域是在一个函数中有效,全局作用域在全局都有效

*函数内部如果变量和全局变量重名了,则在该函数内部,以函数变量为准

*函数外部无法访问函数内部定义的变量(该变量是函数私有的),不过函数内部可以访问函数外部的全局变量

  1.变量提升

javascript中声明并定义一个变量时,会把声明提前,以下会先打印出undefined,再打印出10

1      console.log(a)
2         var a = 10
3         console.log(a)

相当于

1         var a
2         console.log(a)
3         a = 10
4         console.log(a)    

函数声明也是,以下函数相当于把整个fn提到作用域的最上面,所以调用fn时会正常打印jack

1 fn(‘jack‘)
2         function fn (name){
3             console.log(name)
4         }

不过函数表达式不行,以下是一个函数表达式,JavaScript会把var fn提到作用域最上面,没有吧函数提上去,所以会报错

1 fn("jack");
2
3       var fn = function(name) {
4         console.log(name);
5       };

  2.闭包

  使用场景:1.函数作为参数传递  2.函数作为返回值传递

  三言两语说不清楚,我们来看一个demo

 1 function F1(){
 2         var a = 100
 3         //返回一个函数
 4         return function(){
 5             console.log(a)
 6         }
 7       }
 8
 9       var a = 200;
10       var f1 = F1(); //将f1指向F1
11       f1()

第11行输出结果是100

第11行调用f1的时候要打印a变量,return的函数中没有a变量,所以a是个自由变量,要去声明该函数(不是调用)的父级作用域去查找,即functin F1中,a=100

  闭包在开发中的应用

  以下函数的目的是:当_list中没有val值时,返回true并把val添加到_list中

  这个demo使用了闭包,在外部无法直接访问_list这个Fn函数的私有变量,这样可以保证数据不被污染,提高了安全性

 1 function Fn(){
 2           var _list = []
 3
 4           return function(val){
 5               if(_list.indexOf(val) < 0){
 6                   _list.push(val)
 7                   return true
 8               }else{
 9                   return false
10               }
11           }
12       }
13
14       var f1 = Fn()
15       console.log(f1(10))   //true
16       console.log(f1(10))   //false
17       console.log(f1(20))   //true
18       console.log(f1(20))   //false

异步和单线程

  异步和单线程是相辅相成的,js是一门单线程脚本语言,所以需要异步来辅助

  异步和同步的区别: 异步会阻塞程序的执行,同步不会阻塞程序的执行,

          比如只有在执行完alert后才会打印100,如果你不去点击弹框的确定键,console.log就永远不会执行,这就是同步的阻塞

           第二个demo中,会马上就打印100,两秒后再打印setTimeout,这就是异步不会阻塞程序执行

1     alert(‘ook‘)
2      console.log(100)
1 setTimeout(function(){
2             console.log(‘setTimeout‘)
3         },2000)
4         console.log(100)

  在哪些场景中会异步执行

  JavaScript中以下三种情况会异步执行  1.定时任务:setTimeout, setInterval  2.网络请求:ajax请求,动态加载<img>图标  3.事件绑定:比如‘click’等

  看一个demo

  以下函数的目的是在页面中创建5个a标签,点击第一个a标签打印1,点击第二个a标签打印2,以此类推。可执行结果都是5,为什么呢?

  因为click是一个异步事件,计算机不知道用户什么时候会点击,所以不能够是同步,不然用户不点击,程序就永远无法往下执行。

  异步事件会先拿出来放到一个队列里,等同步事件执行完了,再来执行异步事件

  所以当你点击a标签的时候,i已经循环到5了(i是全局变量。这也涉及到了js作用域:该函数没有定义i变量,就要去声明该函数的父级作用域中去找,而不是调 用)

 1     for(var i = 0; i < 5; i++){
 2             //创建一个a标签
 3             var a = document.createElement(‘a‘)
 4             a.innerHTML = i + 1 + ‘<br>‘
 5             //给a标签绑定click事件
 6             a.addEventListener(‘click‘, function(e){
 7                 e.preventDefault()
 8                 console.log(i)
 9             })
10             //将a标签添加到wrpper中
11             document.querySelector(‘#wrapper‘).appendChild(a)
12         }

解决这个问题就可以用闭包,用一个function把给a添加时间的地方包起来,(function(i){})(i) 这是函数的自调用。注意:自调用前要加分号,也就是第4行结束要加分号,不然js会分不清何时开始自调用,会报错

 1  for(var i = 0; i < 5; i++){
 2             //创建一个a标签
 3             var a = document.createElement(‘a‘)
 4             a.innerHTML = i+1 + ‘<br>‘;
 5             //给a标签绑定click事件
 6             (function(i){
 7                 a.addEventListener(‘click‘, function(e){
 8                 e.preventDefault()
 9                 console.log(i+1)
10             })
11             })(i)
12             //将a标签添加到wrpper中
13             document.querySelector(‘#wrapper‘).appendChild(a)
14         }

原文地址:https://www.cnblogs.com/zhaozhaoli/p/10051265.html

时间: 2024-10-01 20:43:05

JavaScript基础--------三座大山(前端面试必考)的相关文章

前端面试必考:事件委托

先看几道面试题 描述下js里面的事件流 默认情况下,事件是在冒泡阶段执行还是捕获阶段执行 请简要说明事件委托原理和使用场景 手写原生js实现事件代理,注意浏览器兼容 如果上面的面试题,您不能很顺利的作答,那么希望这篇文件对您能有一些帮助.如果出现错误,请您及时指正,谢谢. 什么是事件委托 事件委托也叫事件代理,<Javascript高级程序设计>中写道:事件委托就是利用事件冒泡,只指定一个事件处理程序,就可以管理某一类型的所有事件. 想要理解事件委托,需要先理解js事件流. js事件流 图为事

95%的技术面试必考的JVM知识点都在这,另附加分思路!

概述:知识点汇总 jvm的知识点汇总共6个大方向:内存模型.类加载机制.GC垃圾回收是比较重点的内容.性能调优部分偏重实际应用,重点突出实践能力.编译器优化和执行模式部分偏重理论基础,主要掌握知识点. 各个部分的内容如下: 1>内存模型部分:程序计数器.方法区.堆.栈.本地方法栈的作用,保存哪些数据: 2>类加载部分:双亲委派的加载机制以及常用类加载器分别加载哪种类型的类: 3>GC部分:分代回收的思想和依据,以及不同垃圾回收算法实现的思路.适合的场景: 4>性能调优部分:常用的j

Java BAT大型公司面试必考技能视频-1.HashMap源码分析与实现

视频通过以下四个方面介绍了HASHMAP的内容 一. 什么是HashMap Hash散列将一个任意的长度通过某种算法(Hash函数算法)转换成一个固定的值. MAP:地图 x,y 存储 总结:通过HASH出来的值,然后通过值定位到这个MAP,然后value存储到这个MAP中的HASHMAP基本原理 1. KEY 是否可以为空?可以,Null当成一个Key来存储 2. 如果Hash KEY重复了会覆盖吗?会覆盖,但返回旧的值 3. HASHMAP什么时候做扩容?put 的时候,阀值高于或等于0.7

MySQL面试必考知识点:揭秘亿级高并发数据库调优与最佳实践法则

做业务,要懂基本的SQL语句: 做性能优化,要懂索引,懂引擎: 做分库分表,要懂主从,懂读写分离... 数据库的使用,是开发人员的基本功,对它掌握越清晰越深入,你能做的事情就越多. 今天我们用10分钟,重点梳理一遍以下几方面: 数据库知识点汇总: 数据库事务特性和隔离级别: 详解关系型数据库.索引与锁机制: 数据库调优与最佳实践: 面试考察点及加分项. 知识点汇总 一.数据库的不同类型 1.常用的关系型数据库 Oracle:功能强大,主要缺点就是贵 MySQL:互联网行业中最流行的数据库,这不仅

Android面试必考基础题

(1)<必考题>请写出Android系统架构有几层,分别是哪几层? 考点:Android系统架构 答案:有四层.分别是Linux内核.本地库和Java运行时环境.应用程序框架.应用程序. (2)<必考题>请简要介绍Android的四大组件? 考点:Android四大组件 答案:Android系统有四种组件,这四种组件构成了Android应用的框架,然后由Intent联系这四种组件.Activity用来显示Android的程序界面,一个应用往往有多个界面,所以一个应用中会有多个Act

HTTP协议详解(前端面试常考知识点)

分类:杂谈| 发布:佚名| 查看:70 | 发表时间:2014-2-17 引言 HTTP是一个属于应用层的面向对象的协议,由于其简捷.快速的方式,适用于分布式超媒体信息系统.它于1990年提出,经过几年的使用与发展,得到不断地完善和扩展.目前在WWW中使用的是HTTP/1.0的第六版,HTTP/1.1的规范化工作正在进行之中,而且HTTP-NG(Next Generation of HTTP)的建议已经提出.HTTP协议的主要特点可概括如下:1.支持客户/服务器模式.2.简单快速:客户向服务器请

【iOS开发-34】自己主动释放池@autoreleasepool的使用注意事项以及ARC机制——面试必考内容

自己主动释放池@autorelease面试频率可能会吧release还要高. (1)在自己主动释放池@autoreleasepool{}中alloc一个对象后(如p1).仍然须要用[p1 autorelease];不过这个语句和[p1 release];不同.后者表示把p1的retainCount-1,而前者只表示把p1放到自己主动释放池中返回一个self,自己主动释放池结束销毁时,统一对里面的对象引用计数retainCount-1. (2)@autoreleasepool{}能够任意创建.也能

【iOS开发-34】自动释放池@autoreleasepool的使用注意事项以及ARC机制——面试必考内容

自动释放池@autorelease面试频率可能会吧release还要高. (1)在自动释放池@autoreleasepool{}中alloc一个对象后(如p1),仍然需要用[p1 autorelease];只是这个语句和[p1 release];不同,后者表示把p1的retainCount-1,而前者仅仅表示把p1放到自动释放池中返回一个self,自动释放池结束销毁时,统一对里面的对象引用计数retainCount-1. (2)@autoreleasepool{}可以随意创建,也可以嵌套使用.

8个Python面试必考的题目,小编也被坑过 ToT

写在前面 小编学习Python已经三年多了,现在稳定在一家公司快一年了,回想起来一年以前的面试经历真的有点胆战心惊啊! 因为面试题目一不小心就会被坑啊~ 你经历过绝望么? 当你被Python面试题目坑到的时候内心真的一万个草泥马徘徊在心中啊o(╥﹏╥)o 下面小编就分享一些小编亲身经历过的一些Python神坑面试题哦~ 干货来了 1.下面这段代码的输出结果是什么?请解释. def extendList(val, list=[]): list.append(val) return list lis