大前端面试梳理

栏目: JavaScript · 发布时间: 5年前

内容简介:function Animal(name){}

HTML

CSS

Javascript

JS基本介绍

  • JS的用途:Javascript可以实现浏览器端、服务器端(nodejs)。。。
  • 浏览器端JS由以下三个部分组成:

    • ECMAScript:基础语法(数据类型、运算符、函数。。。)
    • BOM(浏览器对象模型):window、location、history、navigator。。。
    • DOM(文档对象模型):div、p、span。。。
  • ECMAScript又名es,有以下重大版本:

    • 旧时代:

      • es1.0。。。es3.1
    • 新时代:

      • es5
      • es6(es2015)
      • es7(es2016)、es8(es2017)

数据类型

  • 基本数据类型——值类型:(数字、字符串、布尔值、null、undefined)

    • undefined类型?
  • 复杂数据类型——引用类型:(对象)

    • 数组
    • 函数
    • 正则表达式
    • Date

对象的基本使用

创建一个对象

var student={ 
        name:"李白" , //student有一个name属性,值为"李白"
        grade:"初一" ,
        //a、student有一个say属性,值为一个函数
        //b、student有一个say方法
        say:function(){
            console.log("你好");
        },
        run:function(speed){
            console.log("正在以"+speed+"米/秒的速度奔跑");
        }
    }

对象是键值对的集合:对象是由属性和方法构成的 (ps:也有说法为:对象里面皆属性,认为方法也是一个属性)

  • name是属性 grade是属性
  • say是方法 run是方法

对象属性操作

获取属性:

第一种方式:.语法

  • student.name 获取到name属性的值,为:"李白"
  • student.say 获取到一个函数

第二种方式:[]语法

  • student["name"] 等价于student.name
  • student["say"] 等价于student.say

2种方式的差异:

  • .语法更方便,但是坑比较多(有局限性),比如:

    • .后面不能使用js中的关键字、保留字(class、this、function。。。)
    • .后面不能使用数字
var obj={};
    obj.this=5; //语法错误
    obj.0=10;   //语法错误
  • []使用更广泛

    • o1[变量name]
    • ["class"]、["this"]都可以随意使用 obj["this"]=10
    • [0]、[1]、[2]也可以使用

      obj[3]=50 = obj["3"]=50
      
    • 甚至还可以这样用:["[object Array]"]

      • jquery里面就有这样的实现
    • 也可以这样用:["{abc}"]

      • 给对象添加了{abc}属性

设置属性

  • student["gender"]="男" 等价于: student.gender="男"

    • 含义:如果student对象中没有gender属性,就添加一个gender属性,值为"男"
    • 如果student对象中有gender属性,就修改gender属性的值为"男"
  • 案例1: student.isFemale=true
  • 案例2: student["children"]=[1,2,5]
  • 案例3:
student.toShanghai=function(){   
        console.log("正在去往上海的路上")   
    }

删除属性

  • delete student["gender"]
  • delete student.gender

通过构造函数创建对象

构造函数创建对象的例子:

  • var xiaoming = new Object() --> var xiaoming = {};
  • var now = new Date()
  • var rooms = new Array(1,3,5) --> var rooms = [1,3,5]
  • var isMale=/123/; ==> var isMale=new RegExp("123")

    • isMale是通过RegExp构造函数创建出来的对象
    • isMale是RegExp构造函数的实例
  • 以上例子中,Object、Date、Array都是内置的构造函数

自定义一个构造函数来创建对象

  • 构造函数
function Person(name,age){
        this.name=name;
        this.age=age;
    }
    var p1=new Person("赵云",18)
  • 说明: p1就是根据【Person构造函数】创建出来的对象

构造函数的概念

  • 任何函数都可以当成构造函数
    function CreateFunc(){ }
  • 只要把一个函数通过new的方式来进行调用,我们就把这一次函数的调用方式称之为:构造函数的调用

    • new CreateFunc(); 此时CreateFunc就是一个构造函数
    • CreateFunc(); 此时的CreateFunc并不是构造函数

关于new Object()

  • new Object()等同于对象字面量{}

构造函数的执行过程

var p1=new Person();

  • 1、创建一个对象 (我们把这个对象称之为Person构造函数的实例)- _p1
  • 2、创建一个内部对象, this ,将this指向该实例(_p1)
  • 3、执行函数内部的代码,其中,操作this的部分就是操作了该实例(_p1)
  • 4、返回值:

    • a、如果函数没有返回值(没有return语句),那么就会返回构造函数的实例(p1)
    • b、如果函数返回了一个基本数据类型的值,那么本次构造函数的返回值是该实例(_p1)
    function fn(){
            
        }
        var f1=new fn();    //f1就是fn的实例
    
        function fn2(){
            return "abc";
        }
        var f2=new fn2();   //f2是fn2构造函数的实例
    • c、如果函数返回了一个复杂数据类型的值,那么本次函数的返回值就是该值
    function fn3(){
            return [1,3,5]; 
            //数组是一个对象类型的值,
            //所以数组是一个复杂数据类型的值
            //-->本次构造函数的真正返回值就是该数组
            //-->不再是fn3构造函数的实例
        }
        var f3=new fn3();   //f3还是fn3的实例吗?错
        //f3值为[1,3,5]

继承

JS中继承的概念:

  • 通过【某种方式】让一个对象可以访问到另一个对象中的属性和方法,我们把这种方式称之为继承 并不是所谓的xxx extends yyy

为什么要使用继承?

  • 有些对象会有方法(动作、行为),而这些方法都是函数,如果把这些方法和函数都放在构造函数中声明就会导致内存的浪费
function Person(){
        this.say=function(){
            console.log("你好")
        }
    }
    var p1=new Person();
    var p2=new Person();
    console.log(p1.say === p2.say);   //false

继承的第一种方式:原型链继承1

Person.prototype.say=function(){
        console.log("你好")
    }
  • 缺点:添加1、2个方法无所谓,但是如果方法很多会导致过多的代码冗余

继承的第二种方式:原型链继承2

Person.prototype={
        constructor:Person,
        say:function(){
            console.log("你好");
        },
        run:function(){
            console.log("正在进行百米冲刺");
        }
    }
  • 注意点:
  • a、一般情况下,应该先改变原型对象,再创建对象
  • b、一般情况下,对于新原型,会添加一个constructor属性,从而不破坏原有的原型对象的结构

继承的第三种方式:拷贝继承(混入继承)

  • 场景:有时候想使用某个对象中的属性,但是又不能直接修改它,于是就可以创建一个该对象的拷贝
  • 实现1:
var source={name:"李白",age:15}
    var target={};
    target.name=source.name
    target.age=source.age;
  • 上面的方式很明显无法重用,实际代码编写过程中,很多时候都会使用拷贝继承的方式,所以为了重用,可以编写一个函数把他们封装起来:
function extend(target,source){
        for(key in source){
            target[key]=source[key];
        }
        return target;
    }
    extend(target,source)
  • 由于拷贝继承在实际开发中使用场景非常多,所以很多库都对此有了实现

    • jquery:$.extend
  • es6中有了对象扩展运算符仿佛就是专门为了拷贝继承而生:
var source={name:"李白",age:15}
    var target={ ...source }

继承的第四种方式:原型式继承

  • 场景:

    • 创建一个纯洁的对象
    • 创建一个继承自某个父对象的子对象
  • 使用方式:

    • 空对象:Object.create(null)
    var o1={ say:function(){} }
        var o2=Object.create(o1);

继承的第五种方式:借用构造函数实现继承

  • 场景:适用于2种构造函数之间逻辑有相似的情况

function Animal(name){

this.name=name;

}

function Person(name,age){

this.name=name;
this.age=age;

}

  • 以上代码用借用构造函数实现
function Animal(name,age){
    this.name=name;
    this.age=age;
}
function Person(name,age,address){
    Animal.call(this,name);
    //this.name=name;
    //this.age=age;
    this.address=address;
}

原型链

闭包

变量作用域

  • 变量作用域的概念:就是一个变量可以使用的范围
  • JS中首先有一个最外层的作用域:称之为全局作用域
  • JS中还可以通过函数创建出一个独立的作用域,其中函数可以嵌套,所以作用域也可以嵌套

作用域链

  • 由于作用域是相对于变量而言的,而如果存在多级作用域,这个变量又来自于哪里?这个问题就需要好好地探究一下了,我们把这个变量的查找过程称之为变量的作用域链
  • 简单来说,作用域链可以用以下几句话来概括:(或者说:确定一个变量来自于哪个作用域)

    • 查看当前作用域,如果当前作用域声明了这个变量,就确定结果

      • 查找当前作用域的上级作用域,也就是当前函数的上级函数,看看上级函数中有没有声明

        • 再查找上级函数的上级函数,直到全局作用域为止

          • 如果全局作用域中也没有,我们就认为这个变量未声明(xxx is not defined)
  • 举例1:
var name="张三";
    function f1(){
        var name="abc";
        console.log(name);
    }
    f1();
  • 举例2:
var name="张三";
    function f1(){
        console.log(name);
        var name="abc";
    }
    f1();
  • 举例3:
var name="张三";
    function f1(){
        console.log(name);
        var name="abc";
    }
    f1();
  • 举例4:
var name="张三";
    function f1(){
        return function(){
            console.log(name);
        }
        var name="abc";
    }
    var fn=f1();
    fn();
  • 举例5:
var name="张三";
    function f1(){
        return {
            say:function(){
                console.log(name);
                var name="abc";
            }
        }
    }
    var fn=f1();

闭包的问题

function fn(){
        var a=5;
        return function(){
            a++;
            console.log(a);
        }
    }
    var f1=fn();
    f1();
    f1();
    f1();

闭包问题的产生原因

  • 函数执行完毕后,作用域中保留了最新的a变量的值

闭包的应用场景

  • 模块化
  • 防止变量被破坏

es6内容

  • 1、解构赋值
  • 2、函数rest参数
  • 3、箭头函数

    • 箭头函数和普通函数有哪些不同?(4点)
  • 4、对象的Object.assign
  • 5、promise
  • 6、generator
  • 7、async
  • 8、class
  • 9、module

原型

  • 原型很多人开发用不到?

    • 很多人都用es6/7/8开发,确实用的比较少
    • 如果你用es5之前的版本开发代码(IE8、IE7。。。),可能天天都要写原型
    • 理解了原型,才是理解了JS面向对象的核心,没有理解原型,你就没有理解面向对象的核心

ES6

node.js

vue

React

Angular

微信


以上所述就是小编给大家介绍的《大前端面试梳理》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Game Programming Patterns

Game Programming Patterns

Robert Nystrom / Genever Benning / 2014-11-2 / USD 39.95

The biggest challenge facing many game programmers is completing their game. Most game projects fizzle out, overwhelmed by the complexity of their own code. Game Programming Patterns tackles that exac......一起来看看 《Game Programming Patterns》 这本书的介绍吧!

HTML 压缩/解压工具
HTML 压缩/解压工具

在线压缩/解压 HTML 代码

URL 编码/解码
URL 编码/解码

URL 编码/解码

SHA 加密
SHA 加密

SHA 加密工具