JS知识点

JS高级与面向对象

2017-04-05  本文已影响0人  福尔摩鸡

一、JavaScript基础知识回顾

1.1 JavaScript

1.1.1 javascript是什么?

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

1.1.2 javascript的组成

1.1.3 ECMAScript与JavaScript的关系

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

1.1.4 JavaScript中的数据类型

1.1.5 JavaScript中的语句

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 对象创建方式

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 构造函数的返回值

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 相关概念

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 对象中属性的判断

//小测试:
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 原型链

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 借用构造函数继承

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 函数的原型链

2.7.2 函数的三种角色

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

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

2.7.3 函数的定义方式

2.7.4 this的不同指向场景

2.7.5 高阶函数

高阶函数

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 基本类型与引用类型深入理解

2.8.3 标准库

2.8.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 作用域

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

作用域链:链是一个对象列表(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 函数相关属性补充

2.11.2 事件处理机制

2.11.3 事件绑定方式

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

2.11.5 自定义事件

2.12 正则

2.12.1 正则相关API

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);
}

3.2.2 window中的undefined

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

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 跨域解决方案有哪些?

3.6 DNS解析过程是什么?

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 锚点 定位页面的某一部分

上一篇下一篇

猜你喜欢

热点阅读