前端面试-面向对象、原型链、封装、继承、闭包

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_34664239/article/details/88287872

一、面向对象和基于对象

  • 面向对象有三大特性:封装、继承、多态
  • 基于对象:有封装的概念,但是实现不了真正的继承。通常是使用对象,但是无法利用现有的对象模板产生新的对象类型,继而产生新的对象,也就是说“基于对象”没有继承的特点。
  • JavaScript是基于对象的语言,有三大特点:基于对象、多范式(多样化,没有统一的标准,比如创建对象和数组的方式)、动态性

面向对象:是先有一个抽象的对象描述(类),然后根据这个描述去构建新的对象(实例化对象),就好像盖房子,这个是根据图纸盖
基于对象:是先有一个具体的对象,然后根据这个具体的对象,再去创建新的对象(实例化对象),就好像盖房子,这个是根据盖好的房子的样子盖

原型链

  • 原型:把所有可以共享的数据放在同一个对象中,再创建对象的时候,不会出现代码冗余,节省内存。(作用:实现同类对象之间的数据共享)
  • 只要是函数,都会有原型。由此函数创建出来的对象,都能访问原型上的成员
  • 获取原型:
    • 通过函数:fnName.prototype
    • 通过对象:obj.proto
    • //获取对象的原型兼容处理
function getPrototype(obj){
   return obj.__proto__ ? obj.__proto__ : obj.constructor.prototype;
}
原型特点:动态性、唯一性、不可变性、共享性
  • 动态性:在已有的原型上添加成员,会反应到创建出来的对象上
    如果置换了已有的原型,那么会反映到后来创建的对象上,对已经创建出来的对象没有影响
  • 唯一性:由同一个构造函数创建出来的所有对象,都共享一个原型
  • 不可变性:通过对象不能修改原型上的值(只能通过修改原型,来改变原型的属性值)
  • 共享性:所有对象都可以直接访问原型上的成员

注意:在函数创建的对象上,给原型加方法,仍然可以共享

二、原型链

在这里插入图片描述
只有函数有原型prototype!
所有对象都有__proto__属性!

对象的 proto 属性指向创建该对象的函数的 prototype!
函数的 proto 属性指向 Function.prototype!

函数的原型的构造函数指向该函数!
函数的原型的__proto__属性指向Object.prototype!
Object.prototype的__proto__属性指向null!

 //对象是由函数生成的,对象的__proto__属性是从生成它的函数的prototype那里得来的
var obj = {};//var o = Object();//Object函数
console.log(obj.__proto__ === Object.prototype )
//普通函数创建对象
var f = function(){};
var a = new f;
console.log(a.__proto__ === f.prototype )
//函数对象都是由Function函数生成的:
function fn(){}
console.log(fn.__proto__ === Function.prototype)
//Function函数本身作为对象时,生成它的函数是他自身!
console.log(Function.__proto__ === Function.prototype)
//Object函数既然是函数,那生成它的函数自然是Function函数
console.log(Object.__proto__ === Function.prototype)

//一般函数默认的prototype是一个类型为"object"的对象,
//它有两个属性:constructor和 __proto__。
//其中constructor属性指向这个函数自身,__proto__属性指向Object.prototype,这说明一般函数的prototype属性是由Object函数生成的。
function ff(){}
console.log(ff.prototype.constructor === ff)
console.log(Function.prototype.constructor === Function)
console.log(ff.prototype.__proto__ === Object.prototype)

//特殊情况:JavaScript原型链的终点
console.log(Object.prototype.__proto__ === null)
console.log(Function.prototype.__proto__ === Object.prototype)
/* 

用instanceof,来判断__proto__走向
instanceof作用:用于判断实例属于哪个构造函数
instanceof原理:判断实例对象的__proto__属性,和构造函数的prototype属性,是否为同一个引用(是否指向同一个地址)。
在这里插入图片描述

三、封装

封装就是方便的使用同一个方法,达到实现既定效果的目的。一般都会采用,将这个共同的方法写在原型中,实例指向的原型是一样的,不会消耗内存

(function() {
    /***
     * 信息提示组件Toast v1.0
     * @param {Object} container 内容容器(必填)
     * @param {Object} content 文字内容(可选)
     * @param {Object} duration 显示时长(可选)
     * 使用方法
     * var toast = new Toast("toast", "你好,对话框");
     * toast.show();(支持回调函数)
     */
    function Toast(container, content, duration) {
        this.container = document.getElementById(container);
        this.content = content || "这是一段对话";
        this.duration = duration || 2000;
    }

    Toast.prototype.show = function(callback) {
        this.callback = callback || function() {};
        this.container.style.opacity = 1;
        this.container.style.display = "block";
        this.container.innerHTML = this.content;

        setTimeout(function() {
            this.callback && this.callback();
            this.hide();
        }.bind(this), this.duration);

        return this;
    }
    window.Toast = Toast;

})(window);

四、继承

https://blog.csdn.net/qq_34664239/article/details/83785441

五、闭包

优点:不产生全局变量,实现属性私有化。
缺点:闭包中的数据会常驻内存,在不用的时候要删掉否则会导致内存溢出。

function outFun() {
    var num = 10;
    function inFun() {   //  内部的函数可以使用外部的函数 变量
        console.log(num);
    }
    return inFun;  // 注意:不带括号!!不带括号返回函数体,带括号返回函数值
}
var obj = outFun();
// obj = function inFun() { console.log(num)}
obj();

//tab -- 闭包的节流
window.onload = function(){
   //要想多个盒子不相互影响 ,我们可以通过id 给他们分开
   //封装tab栏切换函数
   function tab(obj){
       var target = document.getElementById(obj);
       var spans = target.getElementsByTagName("span");
       var lis = target.getElementsByTagName("li");
       for(var i=0;i<spans.length;i++)
       {
           //  spans[i].index = i;
           var timer = null;
           spans[i].onmouseover =  function (num) {
               return function(){
                   clearTimeout(timer);
                   timer = setTimeout(function(){
                       for(var j=0; j<spans.length;j++)
                       {
                           spans[j].className = "";
                           lis[j].className = "";
                       }
                       spans[num].className = "current";
                       lis[num].className = "show";
                   },300)

               }
           }(i);
           spans[i].onmouseout = function() {
               clearTimeout(timer);
           }


       }
   }
   tab("one");
   tab("two");
   tab("three");
}

猜你喜欢

转载自blog.csdn.net/qq_34664239/article/details/88287872