JS高级与面向对象

一、JavaScript基础知识回顾

1.1 JavaScript

1.1.1 javascript是什么?

JavaScript是一门编程语言,用来操作页面标签和样式。

1.1.2 javascript的组成

  • ECMAScript:可以为不同种类的宿主环境提供核心的脚本编程能力,因此核心的脚本语言是与任何特定的宿
    主环境分开进行规定的。Web 浏览器对于 ECMAScript 来说是一个宿主环境,但它并不是唯一的宿主环境。
    ECMAScript描述了以下内容:语法、类型、语句、关键字、保留字、运算符、对象。
  • DOM:(Document Object Model 文档对象模型)是 HTML 和 XML 的应用程序接口(API)。DOM 将把
    整个页面规划成由节点层级构成的文档。HTML 或 XML 页面的每个部分都是一个节点的衍生物。用 DOM
    API 可以轻松地删除、添加和替换节点。
  • BOM:(Browser Object Model 浏览器对象模型)可以对浏览器窗口进行访问和操作。

1.1.3 ECMAScript与JavaScript的关系

前者是后者的规格,后者是前者的一种实现。

1.1.4 JavaScript中的数据类型

  • 基本类型:number string boolean null undefined
  • 引用类型:object (Array Date Math(比较特别) RegExp Function Object Error Number String Boolean XMLHttpRequest )
  • 基本类型与引用类型的差别:
    • 存储方式不同:基本类型数据存储在栈stack;引用类型存储在堆heap。
    • 赋值方式不同:基本类型赋值的时候传递的是具体的值;引用类型赋值的时候传递的是内存的地址。

1.1.5 JavaScript中的语句

  • 分支:if,if else,switch
  • 循环:do while,while,for,for in

1.2 异常处理

作用:

  • 防止某些程序出错时影响后面代码的执行。
  • 屏蔽底层的报错细节,从而给用户一个友好提示。
var abc = 123;
try{
    var data = false;
    if(!false){
        throw new Error('数据格式异常');
    }
    //try当中的代码一旦发生错误,try当中之后的代码就不再执行了
    console.log(abc);
}catch(e){
    //只有try当中的代码发生错误,这里才会执行
    console.log(e.message);//表示错误原因
    console.log(e.name);//表示错误类型
}finally{
    //无论try当中的代码是否执行,这里都会执行
    console.log(abc);
}

二、面向对象

2.1 面向对象概述

2.1.1 什么是对象

所谓的对象就是某种事物,万物皆对象。

用程序的方式描述对象:属性+行为。

2.1.2 对象创建方式

  • 字面量:各种数据类型的字面量表示。

    var obj1 = {
      username : '张三',
      age : 12,
      gender : 'male'
    };
    
  • 构造函数:内置对象和自定义对象。

    var obj2 = new Object();
    obj2.username = '李四';
    obj2.age = 13;
    obj2.gender = 'female';
    

    如果构造函数不需要传递参数,那么后面的括号可以省略。

    var obj = new Object();
    var obj = new Object;
    

2.1.3 属性的访问方式

  • 对象名.属性名称
  • 对象名['属性名称']

两种方式的区别:方括号的方式可以使用变量。

2.1.4 实例化的本质

构造函数实例化对象本质上做了什么工作?

  1. 开辟堆内存用来存储实例中数据(属性和方法)。
  2. 用this指向该区域。
  3. 通过this向该区域中放置数据。
  4. 返回this
function Foo(info){
        // 构造函数中的this指的是构造函数所创建的实例对象
        this.info = info;
        this.showInfo = function(){
            // 实例方法中的this指向方法的调用者(实例对象本身)
            console.log(this.info);
        }
        // 构造函数的默认返回值就是this
    }
    var foo = new Foo('tom');
    foo.showInfo();

    var foo1 = new Foo('jerry');
    foo1.showInfo();

2.1.5 构造函数的返回值

  • 构造函数如果显示的返回基本数据类型,那么和不返回等效。
  • 构造函数如果显示的返回引用数据类型,那么就以此为准,就不再返回默认的this了。
function Person(name){
    this.name = name;
    return 123;         //输出:Person {name: "zhangsan"}
    return 'hello';     //输出:Person {name: "zhangsan"}

    return {
        name : 'lisi',
        age : 12
    };                  //输出:Object {name: "lisi", age: 12}
    return [1,2,3];     //输出:[1,2,3]
}
var p = new Person('zhangsan');
console.log(p);

2.1.6 对象原型

JavaScript中对象的本质:无序的键值对集合。

原型:实现数据共享(实例对象之间进行数据共享)。

function Foo(info){
this.info = info;
this.showInfo = function(){
console.log(this.info);
}
}
var f1 = new Foo('tom');
var f2 = new Foo('jerry');
console.log(f1.showInfo === f2.showInfo);//false
-------------------------------------------------------------------------------
function fn(){
    console.log(this.name);
}
function Person(name,age){
    this.name = name;
    this.age = age;
    this.showName = fn;
}
var p1 = new Person('zhangsan');
var p2 = new Person('lisi');
console.log(p1.showName === p2.showName);//true

2.1.7 原型分析

原型:函数都有一个原型属性prototype,该属性值本质上也是对象(实际就是Object的实例)。

原型的作用:实现数据共享(实例对象之间进行共享);实现继承。

__proto__:构造函数产生的实例对象都有一个属性__proto__,该属性不是标准属性,不可以在编程中使用,实际上该属性是浏览器内部使用的,该属性和构造函数中的prototype指向相同。

__proto__属性在实例对象中,prototype属性在构造函数中,这两个属性的指向是相同的。

function Person(name,age){
    this.name = name;
    this.age = age;
}

Person.prototype.showName = function(){
    console.log(this.name);
}
Person.prototype.showAge = function(){
    console.log(this.age);
}
Person.prototype.flag = 123;
Person.prototype.arr = ['red','green','blue'];

var p1 = new Person('tom',12);
p1.flag = 456;
p1.arr.push('pink');
var p2 = new Person('jerry',13);

console.log(p1.flag,p2.flag);   //456 123
console.log(p1.arr,p2.arr);     //["red", "green", "blue", "pink"] ["red", "green", "blue", "pink"]

//解释:
//通过对象.属性名称=值  这种做法会向对象中添加一个属性
//但是obj.arr.push(123); 这种结构不会再obj中添加属性,而会obj.arr数组中添加一项数据

2.2 面向过程与面向对象

2.2.1 相关概念

  • 面向对象是一种编程模式,就是以对象的方式写代码。

    三大特性:封装、继承那个、多态。

  • 面向过程的编程模式的缺点:团队开发容易产生命名冲突;不方便代码的重用;可维护性差。

  • JavaScript面向对象相关概念:

    1. 构造函数
    2. 实例对象
    3. 原型

2.2.2 面向对象开发

//实现如下功能:点击一个按钮改变div的背景色
//用面向对象的风格封装(构造函数+原型)

function ChangeColor(btnId,divId){
    this.btn = document.getElementById(btnId);
    this.div = document.getElementById(divId);
}

ChangeColor.prototype.init = function(){
    // 原型方法中的this指的是该原型所属的构造函数的实例化对象,实际上与构造函数中的this指向相同
    var that = this;//缓存实例对象
    this.btn.onclick = function(){
        // 这里的this是绑定事件函数的DOM对象
        that.div.style.backgroundColor = 'yellow';
    }
}

onload = function(){
    var cc = new ChangeColor('btn','div1');
    cc.init();
}

//不同的this场景:
//1、构造函数中的this
//2、原型方法中的this
//3、事件方法中的this

//1) 构造函数中的this和原型方法中的this指向相同:都是指向实例对象
//2)事件方法中的this指的是绑定事件的对象

2.2.3 对象中属性的判断

  • in:判断对象中是否存在某个属性(属性在实例对象和原型对象都可以)。
  • hasOwnProperty():判断属性是否在实例对象上。
//小测试:
if('a' in window) {
    var a = 123
    console.log(a);
}
//输出:123
//考点:
//1.全局作用域中的变量和函数都是window对象的成员
//2.预解析
//3.js中没有块级作用域
//实现一份方法,判断某个属性是否在原型上
function check(attr,obj){
    if(attr in obj && !obj.hasOwnProperty(attr)){
        return true;
    }else{
        return false;
    }
}

2.3 构造函数、原型与实例的关系

2.3.1 构造函数、原型与实例的关系

  1. 构造函数中都有原型属性prototype,该属性值本质也是对象(Object的实例对象)
  2. 原型对象中都有一个属性constructor,该属性指向原型所属的构造函数
  3. 实例对象中都有一个属性__proto__,该属性不是标准属性,不可以在编程中使用,实际上是浏览器内部使用的,并且该属性指向原型对象。

2.3.2 原型链

  • 原型链:实例对象和原型对象之间形成的有限链式结构,该链式结构通过__proto__连接起来,用于实现继承和共享属性。

  • 对象是有原型对象的,原型对象也有原型对象,原型对象也有原型对象,对象的原型对象一直往上找,会找到一个null。

    var obj = new Object();
    // obj -> Object.prototype -> null
    
    var arr = new Array();
    // arr -> Array.prototype -> Object.prototype -> null
    
    var date = new Date();
    // date -> Date.prototype -> Object.prototype -> null
    
  • 原型链的结构可以通过重置原型对象的方式来修改。

    function Foo1(info){
        this.info = info;
    }
    Foo2.prototype = new Foo1('tom');
    //Foo2.prototype.constructor = Foo1;
    function Foo2(info){
        this.info = info;
    }
    Foo3.prototype = new Foo2('jerry');
    //Foo3.prototype.constructor = Foo2;
    function Foo3(info){
        this.info = info;
    }
    var f = new Foo3('spike');
    console.dir(f);
    
    // f -> new Foo2('jerry') -> new Foo1('tom') -> Foo1.prototype -> Object.prototype -> null
    

2.4 继承

继承:别人的拿过来,自己的还是自己的。可以通过修改原型的指向来实现。

2.4.1 原型继承

function Animal() {
    this.name = '动物';
}

function Tiger(color) {
    this.color = color;
}
Tiger.prototype = new Animal();
var tiger = new Tiger('黄色');
console.log(tiger.name);
console.log(tiger.color);

缺点:没有办法给基础过来的属性赋值,而不影响所有的实例。继承过来的引用类型的数据,所有的实例时共享的。

2.4.2 借用构造函数继承

  • call和apply的基本使用:

    1. call和apply可以调用函数。
    2. 改变所调用函数内部的this指向。
    3. 在非严格模式下,普通函数中this是window;在严格模式下,普通函数中this是undefined。
  • 借用构造函数继承:

    function Person(name,favour){
        this.name = name;
        this.favour = favour;
    }
    
    Person.prototype.showName = function(){
        console.log(this.name);
    }
    
    function Student(num,name,favour){
        // 这里的this是Student构造函数的实例
        // Person.call(this,name,favour);
        Person.apply(this,[name,favour]);
        this.num = num;
    }
    
    var stu1 = new Student(1,'zhangsan',['coding']);
    stu1.favour.push('swimming');
    var stu2 = new Student(2,'lisi',['dancing']);
    
    console.dir(stu1);
    console.dir(stu2);
    stu1.showName();
    

    缺点:没有办法继承父级构造函数原型上的成员。

2.4.3 组合继承

function Person(name,age){
    this.name = name;
    this.age = age;
}
Person.prototype.show=function(){
    console.log(this.name+"今年"+this.age+"岁了");
}
Person.prototype.flag=1;

function Teacher(name,age,level){
    Person.call(this,name,age);
    this.level=level;
}
Teacher.prototype=new Person();

var t1 = new Teacher("张三",33,"T5");
var t2 = new Teacher("李四",30,"T4");
t1.show();

2.5 Object.create的基本使用

//ES5新特性,方法的作用:创建对象
var create = function(obj){
    if(Object.create){
        return Object.create(obj);
    }else{
        function F(){}
        F.prototype = obj;
        return new F();
    }
}

2.6 属性的复制

2.6.1 浅拷贝

var obj = {};
var obj1 = {
    username : 'zhangsan',
    age : 12,
    gender : 'male'
}
function extend(des,origin){
    for(var key in origin){
        des[key] = origin[key];
    }
}
extend(obj,obj1);
console.log(obj);

2.6.2 深拷贝

function foo(set){
    var defaultSettings = {
        width : '100',
        height : '200',
        backgroundColor : 'gray',
        sets : {
            flag : 12,
            abc : 'message'
        }
    }
    var obj = {
        www : 'www'
    }
    var obj1 = {
        qqq : 'qqq'
    }
    $.extend(true,defaultSettings,set,obj,obj1);
    console.dir(defaultSettings);
    console.log(defaultSettings.width);
    console.log(defaultSettings.sets.flag);
    console.log(defaultSettings.sets.abc);
}

var settings = {
    width : '1000',
    sets : {
        flag : 123,
    }
}
foo(settings);

2.7 函数

2.7.1 函数的原型链

  • Function
    1. 所有的函数都是Function的实例。
    2. Funciton也是一个函数。

2.7.2 函数的三种角色

  1. 构造函数
  2. 普通函数
  3. 函数作为对象
function Foo(){}
var foo = new Foo();    //构造函数
Foo();                  //普通函数
Foo.info = 'hello';     //函数作为对象

函数到底是哪种角色,取决于函数的调用方式

2.7.3 函数的定义方式

  • 系统函数(类库、库函数)

  • 自定义函数

    1. 函数声明

      function foo(){
         console.log(123);
      }
      
    2. 函数表达式

      var fn = function(){
          console.log(456);
      }
      fn();
      
    3. new Function()

      var fn1 = new Function('console.log(789);');//需要把字符串转成js代码并执行,性能没有前两者好
      fn1();
      

    区别

    1. 函数声明是在预解析阶段创建的,而函数表达式是在程序执行阶段创建的。
    2. 函数声明只能在全局或者函数内部定义,而函数表达式只能在表达式中定义。
  • 函数都是对象,但对象不一定是函数。

  • Math不是函数,而是对象

2.7.4 this的不同指向场景

  • 函数的调用方式:(函数中的this指向取决与函数的调用方式)

    1. 构造函数
    2. 普通函数
    3. 对象方法
    4. call和apply调用(bind)
  • this的不同指向:

    1. 构造函数中的this指向实例对象
    2. 原型方法中的this指向实例对象,与构造函数中的this指向相同
    3. 在非严格模式下,普通函数中的this指向window,在严格模式下,普通函数中的this指向undefined
    4. 对象方法中的this就是调用方法的对象
    5. 事件方法中的this指的是绑定事件的对象
    6. 定时函数中的this指的是window
    7. call或apply所调用的函数中的this就是call或apply中的第一个参数(该参数必须是引用类型)
  • bind的基本用法:

    • bind方法是ES5的新特性(函数的柯里化)
    • bind用来改变函数内部的this指向,但是不调用函数,并且bind会返回一个新函数(其实还是原来的函数内容,只是this改变为bind中的第一个参数,该参数必须为引用类型)
    var inner = function(a,b){
        console.log(a+b);
    }
    var newInner = inner.bind({info:'hello'},12,13);
    setTimeout(newInner,1000);
    

2.7.5 高阶函数

高阶函数

  • 作为参数的函数

    function foo(fn) {
      var data = {
          info: 'hello'
      }
      fn(data);
    }
    var fn = function(data) {
      console.log(data.info);
    };
    foo(fn);
    
  • 作为返回值的函数(闭包)

    function foo(){
      var num = 1;
      return function(){
          return num++;
      }
    }
    var fn = foo();
    var r1 = fn();
    var r2 = fn();
    console.log(r1,r2);
    

2.8 对象加深

2.8.1 对象的体系结构

  1. 所有的实例对象都有一个__proto__属性,该属性指向产生实例对象的构造函数的原型。
  2. 所有的构造函数都有一个prototype属性,该属性本质上也是一个对象(Object的实例对象)
  3. 所有的原型对象都有一个constructor属性,该属性指向原型所属的构造函数。
  4. 原型对象中有一个__proto__属性,该属性指向Object.prototype(Object的原型对象中没有__proto__,因为这里就是原型链的终点)
  5. 所有的函数都是Function的实例对象。
  6. Function函数本身也是它自己的实例对象(也就是Function.__proto__===Function.prototype)

2.8.2 基本类型与引用类型深入理解

  • 基本类型

    var num = 123
    function foo(data){
      data = '456';
      return data;
    }
    var ret = foo(num);
    console.log(ret,num);//456 123
    
  • 引用类型

    var arr = [1,2,3];
    function foo(data){
      data.push(4);
      return data;
    }
    var ret = foo(arr);
    console.log(ret,arr);//[1, 2, 3, 4] [1, 2, 3, 4]
    

2.8.3 标准库

  • 常用对象:Object、Array、Date、RegExp、Math、Function、Error
  • 包装对象:Number、String、Boolean

2.8.4 类数组(关联数组)详解

  • 类数组:

    var obj = {
      0 : 'qqq',
      1 : 'www',
      2 : 'eee',
      length : 3
    }
    
  • 类数组转数组:

    var arr = [].slice.call(obj,0);
    
  • delete的用法:

    var obj = {
      info : 'abc',
      username : 'lisi'
    }
    delete obj.info;
    console.log(obj);//Object {username: "lisi"}
    var flag = 123;
    delete flag;
    console.log(flag);//123
    
    1. delete的作用就是删除对象的属性。
    2. 全局作用域中var声明的变量,delete无法删除,但是不用var声明的全局变量可以delete删除。
  • 求数组中的最大值:

    //排序
    var arr = [12321,234,99999999,4454,12,454545,343,34,342];
    arr.sort(function(a,b){
        return b - a;
    });
    console.log(arr);//[99999999, 454545, 12321, 4454, 343, 342, 234, 34, 12]
    
    //对象中的Math方法
    var max = Math.max(123,23,4324,45,4,645,6,45645);
    console.log(max);
    
    //借用对象的方法
    var max = Math.max.apply(null,arr);
    console.log(max);
    

    call和apply的应用场景

    1. 调用函数
    2. 改变所调用函数的内部this指向
    3. 转换类数组
    4. 借用别的对象方法

2.9 递归

2.9.1 递归的执行原理

function fn(n){
    if(n == 1){
        console.log('递归结束' + n);
        return 1;
    }else{
        console.log('递归前' + n);
        var ret = n * fn(n-1);
        console.log('递归后' + n);
        return ret;
    }
}
var ret = fn(5);
console.log(ret);

/* 输出结果:
递归前5
递归前4
递归前3
递归前2
递归结束1
递归后2
递归后3
递归后4
递归后5
120
*/

2.9.2 递归的应用

function getChildNodes(node, arr) {
    for (var i = 0; i < node.childNodes.length; i++) {
        var subNode = node.childNodes[i];
        //如果子节点是元素类型就放到数组中
        if (subNode.nodeType == 1) {
            arr.push(subNode);
            //以当前子节点作为新的父节点继续递归
            getChildNodes(subNode, arr);
        }
    }
}
window.onload = function () {
    var arr = [];
    var div = document.getElementById('div');
    getChildNodes(div, arr);
    console.log(arr);
}

2.9.3 jQuery实例化过程

$(function(){
        // var ret = $('.active');
        // console.dir(ret);
        // ret.html('123').css('backgroundColor','green');

        // var aDiv = document.getElementsByTagName('div')[0];
        // console.dir(aDiv);

        // // ret[0];
        // console.log(ret.get(0) === aDiv);

        function jQuery(selector){
           return new jQuery.prototype.init(selector);
        }
        jQuery.prototype = {
            constructor : jQuery,
            html : function(){
                console.log(123);
                return this;
            },
            css : function(){
                console.log(456);
                return this;
            },
            init : function(selector){
                // 实现选择器功能
                // div .active #div1  div span  .active div span
                // Sizzle
                var aDiv = document.getElementsByTagName(selector);
                // 把每一个div都放到this中,那么this就是一个类数组
                [].push.apply(this,aDiv);
                this.length = aDiv.length;
            }
        }
        jQuery.prototype.init.prototype = jQuery.prototype;

        var obj = jQuery('div');
        obj.html('123').css(456);

        // obj.html('hello').css();
        $('div').css('width');//获取某个样式值
        $('div').css('width','100px');//设置样式值
        $('div').css({
            width : '100px',
            height : '100px'
        });
        $('div').css(['width','height']);//{width : 100px,height : 100px}


    });
//待整理

2.10 作用域与闭包

2.10.1 作用域

作用域:指的是变量的作用范围。

  • 全局作用域
  • 函数作用域
  • js没有块级作用域

作用域链:链是一个对象列表(list of objects) ,用以检索上下文代码中出现的标识符(identifiers) 。标示符可以理解为变量名称、函数声明和普通参数。作用域链包括活动对象和父级变量对象。

  • 函数内层作用域可以访问外层作用,但是反过来不可以。

2.10.2 预解析

JavaScript解析器在执行代码的时候分为两个阶段:

  1. 预解析
    • 全局预解析(所有的变量和函数声明都会提前;同名的函数和变量函数的优先级高)
    • 函数内部预解析(所有的变量、函数和形参都会预解析,优先级:函数 > 形参 > 变量)
  2. 从上到下逐行执行

先预解析全局作用域,然后执行全局作用域中的代码,在执行全局代码的过程中遇到函数调用就会先进行函数预解析,然后再执行函数内的代码。

2.10.3 闭包

闭包是一系列代码块(在ECMAScript中是函数),并且静态保存所有父级的作用域。通过这些保存的作用域来搜寻到函数中的自由变量。

当一个函数在自身函数体内需要引用一个变量,但是这个变量并没有在函数内部声明(或者也不是某个参数名),那么这个变量就可以称为自由变量[free variable]。

闭包

  • 封闭的区域
  • 函数的嵌套形成闭包(内层函数和内层函数所处的作用域)
  • 闭包可以操作函数内部的变量(间接的)

闭包的作用

  • 可以缓存中间状态值
  • 延长变量的生命周期
var arr = [];
for (var i = 0; i < 3; i++) {
    arr[i] = (function(num){
        return function(){
            console.log(num);
        }
    })(i);
}
arr[0]();   //0
arr[1]();   //1
arr[2]();   //2

闭包的应用

onload = function(){
    var aInput = document.getElementsByTagName('input');
    for (var i = 0; i < aInput.length; i++) {
        // aInput[i].onclick = (function(){
        //     var num = 0;
        //     return function(){
        //         ++num;
        //         console.log(num);
        //     }
        // })();
        aInput[i].onclick = function(){
            this.num?++this.num:this.num=1;
            console.log(this.num);
            console.dir(this);
        }
    }
}

2.10.4 对象排序

function sortFn(sortName){
    return function(a,b){
        var v1 = a[sortName];
        var v2 = b[sortName];
        if(v1 > v2){
            return 1;
        }else if(v1 < v2){
            return -1;
        }else{
            return 0;
        }
    }
}

2.11 事件

2.11.1 函数相关属性补充

  • arguments 表示实参的集合
  • length 形参的个数
  • caller 函数的调用者
  • name 函数的名称
  • arguments.callee 表示函数本身,但是不推荐使用

2.11.2 事件处理机制

  • 浏览器本身是单线程还是多线程?多线程(多进程)
    1. 页面标签的渲染
    2. 网络通信
    3. 解析js的运行
  • js的运行是单线程的
  • 事件队列(队列中放什么?任务(实际上就是函数))
    1. 定时函数(延时时间到了)
    2. 事件函数(对应的事件触发)
    3. Ajax的回调函数(接收到服务器完整的数据(readyState值发生变化的时候))
  • 事件队列中任务执行的条件:
    1. 主线程空闲
    2. 满足任务的触发条件

2.11.3 事件绑定方式

  • 行内绑定

    点击
  • 给DOM元素直接绑定 btn.onclick

    div.onclick = function(){
      console.log(1);
    }
    
  • addEventListener / attachEvent

    div.addEventListener('click',function(){
      console.log(11);
    },false)
    

2.11.4 阻止冒泡与阻止默认行为

  • 在原生js中,return false只能阻止默认行为,不能阻止冒泡;只能阻止btn.onclick这种方式绑定的事件,不能阻止addEventListener绑定的事件。
  • 在jQuery中,return false既可以阻止冒泡也可以阻止默认行为。

2.11.5 自定义事件

  • 注册事件

    function addEvent(obj,type,fn){
        obj.arrs = obj.arrs || {};
        obj.arrs[type] = obj.arrs[type] || [];
        obj.arrs[type].push(fn);
    }
    var obj = {};
    addEvent(obj,'abc',function(){
        console.log('abc');
    });
    addEvent(obj,'abc',function(){
        console.log('abc1');
    });
    addEvent(obj,'hi',function(){
        console.log('hi');
    });
    
  • 触发事件

    function fireEvent(obj,type){
        var fnList = obj.arrs[type];
        for (var i = 0; i < fnList.length; i++) {
            fnList[i]();
        }
    }
    fireEvent(obj,'hi');
    

2.12 正则

2.12.1 正则相关API

  • 正则的API:

    1. test

      var reg = /\d/;
      console.log(reg.test('123'));
      
    2. exec

      var str = 'adsfasdf123asdfasdf21312sfdsadfad';
      var reg = /\d+/g;
      // var ret = reg.exec(str);
      // console.log(ret);
      var result = null;
      while((result = reg.exec(str)) != null) {
          console.log("Matched `" + result[0] +
                "' at position " + result.index +
                " next search begins at position " + reg.lastIndex);
      }
      
  • 字符串API:

    1. search:查询匹配字符串的索引

      var str = 'dsdaf123asdfasdf';
      console.log(str.search('123'));
      console.log(str.search(/\d+/));
      
    2. match

      //从字符串中找出数字
      var str = '1212adsfasdf123asdfasd234fqewrqew3434rqwerw54qerqwerqwer21321';
      console.log(str.match(/\d+/g));
      
    3. split

      var str = 'zhangsan:12:male;lisi:13:female';
      var arr = str.split(';');
      for (var i = 0; i < arr.length; i++) {
         var item = arr[i].split(':');
         console.log(item[0]);
         console.log(item[1]);
         console.log(item[2]);
      }
      
      var str = 'asdfasdfasdf123asdfas4545dfads';
      var arr = str.split(/\d+/g);
      console.log(arr);
      
    4. replace

      var str = 'adsfasdf123asdfasdf21312sfdsadfad';
      str = str.replace(/\d+/g,'***');
      console.log(str);
      
  • 在非全局匹配模式下,str.match(reg)reg.exec(str)的作用等效。

2.12.2 正则的规则

  • 元字符:

三、面试题

3.1 ==和===相关的比较问题

[] ==![]        //true 
[1] == [1]      //false 
[1] == ![1]     //false

比较规则:

  1. 对象之间的比较是内存地址的比较
  2. 单个空对象转成布尔值是true
  3. 空数组与布尔值的比较会转换成数值的比较(空数组会转化成0)
  4. 转成false的情况:false null '' undefined 0 NaN

3.2 in使用中的问题

3.2.1 变量声明时的问题

console.log('a' in window); //true
if('a' in window){
    var a = 123; 
    console.log(a);
}

console.log('a' in window); //false
if('a' in window){
    a = 123; 
    console.log(a);
}
  • 不使用var不会预解析,但是也会向window中添加属性。

3.2.2 window中的undefined

console.log(a in window); //true
if(a in window){
    var a = 123; 
    console.log(a);
}
  • 不加引号,a是undefined,window中本身就有一个属性undefined,并且undefined的值也是undefined。

3.3 以下代码的输出结果是什么?

var a = {n:1};
var b = a;
a.x = a = {n:2};    //运算符的优先级 .的优先级最高  赋值操作是从右向左运算的
console.log(a.x);   //undefined
console.log(b.x);   //{n:2}

考点:

  1. 基本类型和引用类型
  2. 引用类型变量和对象属性(在内存实际上就是内存地址)
  3. 运算符的优先级.的优先级最高 ,赋值操作是从右向左运算的

3.4 下列代码输出结果是什么?

var a = {name:'zhangsan'}; 
var b = {age : 26}; 
var arr = []; 
arr[a] = 123; 
arr[b] = 456; 
console.log(arr);//Array[0] -->[object Object]:456

数组也是对象

对象属性的访问方式

Object的toString方法作用:把构造函数转成这种形式的字符串:[object Object]

3.5 跨域解决方案有哪些?

  • jsonp
  • cors
  • 反向代理
  • flash插件

3.6 DNS解析过程是什么?

  • DNS Domain Name System : 负责域名和IP地址的映射关系
  • 域名解析的规则:先去本机的hosts文件中查找IP,如果没有找到,就去公网的DNS服务器查找,如果还没有找到,那就无法上网;如果在hosts文件中找到了,那么就返回ip,就不再去公网查找了

3.7 前端有多少种方式可以发送请求?

1)浏览器地址直接输入url
2)表单的action属性
3)a标签href属性
4)img的src属性
5)script的src属性
6)link标签的href属性
7)iframe的src属性
8)Ajax发送请求
9)postMessage h5新的API
10)flash插件也可以
11)location.href

url的规范格式
scheme://host:port/path?query#fragment
echeme 表示协议 http https ftp file ssh
host 表示域名或者IP地址
port 端口 用来确定计算机上的具体某个网络应用程序
path 域名之后,?之前的内容 /abc/qqq/rrr
query 查询字符串,作用是向服务器传递数据,格式:键=值&键=值
fragment hash 锚点 定位页面的某一部分

你可能感兴趣的:(JS高级与面向对象)