美文网首页
继承相关基础知识问答

继承相关基础知识问答

作者: 该帐号已被查封_才怪 | 来源:发表于2016-11-02 20:11 被阅读85次

一、问题

(一)、继承有什么作用?

通过继承可以继承原有函数的一些属性和方法,避免重复定义一些属性和方法,举个例子:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>

    <script type="text/javascript" src="http://apps.bdimg.com/libs/jquery/1.9.1/jquery.min.js"></script>
</head>
<body>

    <script>
        function Person(name) {
            this.name=name;
            console.log(this.name)
        }
        Person.prototype.sayHi=function () {
            console.log("Hi! my name is:"+this.name)
        };
        Person.prototype.sayEyesNum=function () {
            console.log("I have two eyes.")
        };
        function Students(name) {
            this.name=name;
            Person.call(this,name)

        }
        Students.prototype=Object.create(Person.prototype); //这里一定要注意
//与Students.prototype.sayHi 间的顺序,Students.prototype.sayHi应该在后面,否则其会被覆盖掉!!
        Students.prototype.constructor=Students;
        Students.prototype.sayHi=function () {
            console.log("Hi! I am student and my name is"+this.name)
        };
        Students.prototype.sayTeacherName=function () {
            console.log("My Teacher's name is Wang")
        };

        var p1=new Person("ren"),
            stu1=new Students("xue");

    </script>

</body>
</html>

上述代码中,我先定义了一个Person的函数,且在该函数属性上绑定sayEyesNum()这个方法,然后我通过继承的方法,使得Students函数也具有了sayEyesNum()这个方法,而无需重新在Students函数上绑定sayEyesNum()这个方法。

(二)、有几种常见创建对象的方式? 举例说明?
  • 1、工厂模式:
function createPerson( name, age, job ) {
    var o = new Object();
    o.name = name;
    o.age = age;
    o.job = job;
    o.sayName = function() {
        alert(this.name);
    }

    return o;
}

var person1 = createPerson("Nicholas", 29, "software Engineer");
var person2 = createPerson("Greg", 27, "Doctor");

person1.sayName(); //"Nicholas"
person2.sayName(); //"Greg"

工厂模式未能够解决对象识别的问题;

  • 2、构造函数模式
function Person( name, age, job ) {
    this.name = name;
    this.age = age;
    this.job = job;
    this.sayName = function() {
        alert(this.name);
    }
}

var person1 = new Person("Nicholas", 29, "software Engineer");
var person2 = new Person("Greg", 27, "Doctor");

person1.sayName(); //"Nicholas"
person2.sayName(); //"Greg"

构造函数的主要问题是每个方法都会在每个实例上创建一遍。

  • 3、原型模式
function Person(){

}

Person.prototype = {
    constructor: Person,
    name: "Nicholas",
    age: 29,
    job: "software Engineer",
    friends: ["Shelby","Court"],
    sayName: function() {
        alert(this.name);
    }
}

var person1 = new Person();
var person2 = new Person();

person1.friends.push("Van");

alert(person1.friends); //"Shelby,Court,Van"
alert(person2.friends); //"Shelby,Court,Van"
alert(person1.friends === person2.friends); //true

原型模式虽然解决了上述几个问题,但是有时候我们需要某个实例要有自己的方法和属性。因此出现了运用最广泛的组合模式

  • 4、组合使用构造函数模式和原型模式
function Person( name, age, job ) {
    this.name = name;
    this.age = age;
    this.job = job;
    this.friends = ["Shelby","Court"];
}

Person.prototype = {
    constructor: Person,
    sayName: function(){
        alert(this.name);
    }
}

var person1 = new Person("Nicholas", 29, "software Engineer");
var person2 = new Person("Greg", 27, "Doctor");

person1.friends.push("Van");

alert(person1.friends); //"Shelby,Court,Van"
alert(person2.friends); //"Shelby,Court"
alert(person1.friends === person2.friends); //false
alert(person1.sayName === person2.sayName); //true

该组合模式中,构造函数用于定义实例属性,原型用于定义方法和共享属性;

  • 5、动态原型模式
function Person( name, age, job ) {
    //属性
    this.name = name;
    this.age = age;
    this.job = job;

    //方法
    if( typeof this.sayName != "function" ) {
        Person.prototype.sayName = function() {
            alert(this.name);
        }
    }
}

var person = new Person("Nicholas", 29, "software Engineer");
person.sayName();
  • 6、寄生构造函数模式
function SpecialArray() {
    //创建数组
    var values = new Array();

    //添加值
    values.push.apply(values,arguments);

    //添加新方法
    values.toPipedString = function(){
        return this.join("|");
    };

    //返回数组
    return values;
}

var colors = new SpecialArray("red","blue","green");
alert(colors.toPipedString()); //"red|blue|green"

返回的对象与构造函数或者与构造函数的原型之间没有关系;不能依赖instanceof操作符来确定对象的类型。由于存在上述问题,我们建议在可以使用其他模式的情况下,不要使用这种模式。

  • 7、稳妥构造函数模式
function Person( name, age, job ) {
    //创建要返回的对象
    var o = new Object();

    //可以在这里定义私有变量和函数

    //添加方法
    o.sayName = function() {
        alert(name);
    };

    //返回对象
    return o;
}

var person = Person("Nicholas", 29, "software Engineer");
Person.sayName(); //"Nicholas"

与寄生构造函数模式类似,使用稳妥构造函数模式创建的对象与构造函数之间也没什么关系, 因此instanceof操作符对这种对象没有意义。

(三)、下面两种写法有什么区别?
//方法1
function People(name, sex){
    this.name = name;
    this.sex = sex;
    this.printName = function(){
        console.log(this.name);
    }
}
var p1 = new People('饥人谷', 2)

//方法2
function Person(name, sex){
    this.name = name;
    this.sex = sex;
}

Person.prototype.printName = function(){
    console.log(this.name);
}
var p1 = new Person('若愚', 27);

通过第一种方式,People的printName方法是在函数People实例对象里的,因此当后面再新建一个People的实例对象时,又会创建一个printName方法,而不能够像第二种方式那样可以在People函数的属性上共用printName方法,不利于节省空间。

(四)、Object.create 有什么作用?兼容性如何?如何使用?

Object.create的作用是创建一个指定原型和若干个指定属性的对象。

由于Object.create是在ES5后出现的,因此如下浏览器才支持:


桌面端 移动端

它的语法如下:

Object.create(proto, [ propertiesObject ])
  • proto 一个对象: 作为新创建的对象的原型;
  • propertiesObject 可选。该参数对象是一组属性与值,该对象的名称将是新建对象的属性名称,值是描述性属性符。值得注意的是该参数对象不能是undefined,另外该对象自身所拥有的可枚举的属性才有效,也就是说其原型链上的属性是无效的。

举个例子:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>

    <script type="text/javascript" src="http://apps.bdimg.com/libs/jquery/1.9.1/jquery.min.js"></script>
</head>
<body>

    <script>
        var o;
        o = Object.create({}, { p: { value: 42 } });
        // 省略了的属性特性默认为false,所以属性p是不可写,不可枚举,不可配置的:
        o.p = 24;
        o.p  //42

        o.A = 12;
        for (var prop in o) {
            console.log(prop)
        }
        //"A"
        delete o.p;
        //false

    </script>
</body>
</html>
(五)、hasOwnProperty有什么作用? 如何使用?

用来判断某个对象是否含有指定的自身属性。其与in运算符不同,hasOwnProperty会忽略掉原型链上继承到的属性。

其使用语法为obj.hasOwnProperty(prop)

  • prop 为要检测的属性名;
    举个例子:
    <script>
        var car={};
        car.name="bench";
    </script>
从原型链上继承的属性被忽略了
(六)、实现Object.create的 polyfill,如:(ps: 写个 函数create,实现 Object.create 的功能)
var obj = {a: 1, b:2};
var obj2 = create(obj);
console.log(obj2.a); //1

简单模拟:

        function create(obj) {
             function Tem() {}
            Tem.prototype=obj;
             return  new Tem()
        }

真实模拟:

        if (typeof Object.create != 'function') {
            // Production steps of ECMA-262, Edition 5, 15.2.3.5
            // Reference: http://es5.github.io/#x15.2.3.5
            Object.create = (function() {
                //为了节省内存,使用一个共享的构造器
                function Temp() {}

                // 使用 Object.prototype.hasOwnProperty 更安全的引用
                var hasOwn = Object.prototype.hasOwnProperty;

                return function (O) {
                    // 1. 如果 O 不是 Object 或 null,抛出一个 TypeError 异常。
                    if (typeof O != 'object') {
                        throw TypeError('Object prototype may only be an Object or null');
                    }

                    // 2. 使创建的一个新的对象为 obj ,就和通过
                    //    new Object() 表达式创建一个新对象一样,
                    //    Object是标准内置的构造器名
                    // 3. 设置 obj 的内部属性 [[Prototype]] 为 O。
                    Temp.prototype = O;
                    var obj = new Temp();
                    Temp.prototype = null; // 不要保持一个 O 的杂散引用(a stray reference)...

                    // 4. 如果存在参数 Properties ,而不是 undefined ,
                    //    那么就把参数的自身属性添加到 obj 上,就像调用
                    //    携带obj ,Properties两个参数的标准内置函数
                    //    Object.defineProperties() 一样。
                    if (arguments.length > 1) {
                        // Object.defineProperties does ToObject on its first argument.
                        var Properties = Object(arguments[1]);
                        for (var prop in Properties) {
                            if (hasOwn.call(Properties, prop)) {
                                obj[prop] = Properties[prop];
                            }
                        }
                    }

                    // 5. 返回 obj
                    return obj;
                };
            })();
        }

(七)、如下代码中call的作用是什么?
function Person(name, sex){
    this.name = name;
    this.sex = sex;
}
function Male(name, sex, age){
    Person.call(this, name, sex);    //这里的 call 有什么作用
    this.age = age;
}

这里call的作用是在函数Male的运行环境中运行Person函数,让函数Male继承了Person函数的属性和方法;

(八)、补全代码,实现继承
function Person(name, sex){
    // todo ...
}

Person.prototype.getName = function(){
    // todo ...
};    

function Male(name, sex, age){
   //todo ...
}

//todo ...
Male.prototype.getAge = function(){
    //todo ...
};

var ruoyu = new Male('若愚', '男', 27);
ruoyu.printName();
        function Person(name, sex){
           this.name=name;
            this.sex=sex;
        }

        Person.prototype.getName = function(){
            return (this.name)
        };

        function Male(name, sex, age){
            this.name=name;
            this.sex=sex;
            this.age=age;
        }
        Person.prototype.printName=function () {
            console.log(this.name)
        };

        Male.prototype=Object.create(Person.prototype);
        Male.prototype.constructor=Male;
        Male.prototype.getAge = function(){
            return (this.age)
        };

        var ruoyu = new Male('若愚', '男', 27);
        ruoyu.printName();

二、代码

(一)、实现如下dialog 弹窗功能, 参考效果
//功能描述: 
// 1. 可使用 dialog.open() 去打开弹窗
// 2. 当点击确定、取消时可使用用户自定义事件
// 3. dialog 可拖动
// 4. 允许页面展示多个 dialog


function Dialog(){
//todo ...
}


var tpl = '<ul><li>列表1</li><li>列表2</li><li>列表1</li><li>列表1</li></ul>';

$('#open4').on('click',function(){
  var dialog4 = new Dialog();
  dialog4.open({
    title: '欢迎来到饥人谷',
    message: tpl,
    isShowCloseBtn: true,
    isShowConfirmBtn: true,
    onClose: function(){
      alert('close')
    },
    onConfirm: function(){
      alert('确定');
    }
  });
});
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        body{
            position: relative;
        }
        .dialog{
            border-radius: 5px;
            background-color:#eee ;
            box-shadow:0 0 5px 2px rgba(0, 0, 0, 0.5);
            position: absolute;
            top: 30%;
            left: 50%;
            width: 328px;
        }
        .title{
            background-color: #676666;
            padding: 8px 10px;
            color: #fff;
            font-weight: bolder;
        }
        .clearfix:after{
            display: block;
            clear: both;
            content: "";
        }

        a{
            text-align: center;
            text-decoration: none;

        }
        .button a{
            background-color: #e33100;
            padding: 5px 8px;
            border-radius: 5px;
            margin-left: 10px;
            margin-right: 10px;
            color: #fff;
        }
        .button{
            padding:  20px 0;
            text-align: center;
        }
        .title a{
            float: right;
            width: 10px;
            color: #fff;
        }
        .content{
            color:#666 ;
            padding: 10px;
        }
        .draggable{
            cursor: move;
            opacity: 0.8;
        }



    </style>
    <script type="text/javascript" src="http://apps.bdimg.com/libs/jquery/1.9.1/jquery.min.js"></script>
</head>
<body>
    <button id="open1">打开1</button>
    <button id="open2">打开2</button>
    <button id="open3">打开3</button>
    <button id="open4">打开4</button>
    <button id="open5">打开5</button>
    <p>鼠标在 dialog 上左键按下可拖动 dialog</p>

    <p>可创建多个 dialog</p>

    <script>





        //功能描述:
        // 1. 可使用 dialog.open() 去打开弹窗
        // 2. 当点击确定、取消时可使用用户自定义事件
        // 3. dialog 可拖动
        // 4. 允许页面展示多个 dialog

        function Dialog(){
            this.createDialog();
            this.bindEvent();
        }
        Dialog.prototype={
            originOpts:{
                title:"",
                message:"",
                isShowCancelBtn:true,
                isShowConfirmBtn:false,
                onCancel:function () {
                    
                },
                onConfirm:function () {
                    
                }
            },
            open:function (opts) {
                this.setOpts(opts);
                this.setDialog();
                this.showDialog();
            },
            setOpts:function (opts) {
                if (typeof opts==="string"){
                    this.opts=$.extend({},this.originOpts,{message:opts})
                }else if (typeof opts==="object"){
                    this.opts=$.extend({},this.originOpts,opts)
                }

            },

            setDialog:function () {
                var $dialog=this.$dialog;
                console.log($dialog);
                if (!this.opts.title){
                    $dialog.find(".title").hide();
                }else {
                    $dialog.find(".title").show();
                }
                if (!this.opts.isShowCancelBtn){
                    $dialog.find(".button .cancel").hide();
                }else {
                    $dialog.find(".button .cancel").show();
                }
                if (!this.opts.isShowConfirmBtn){
                    $dialog.find(".confirm").hide();
                }else {
                    $dialog.find(".confirm").show();
                }
                $dialog.find(".title span").text(this.opts.title);
                $dialog.find(".content").html(this.opts.message);

            },
            showDialog:function () {
                this.$dialog.show();

            },
            hideDialog:function () {
                this.$dialog.hide();

            },
            createDialog:function () {
                var tp1='<div class="dialog">'+'<div class="title clearfix"><span></span><a class="cancel" href="####">X</a></div>'+'<h3 class="content"></h3>'+'<div class="button"><a class="cancel" href="####">取消</a><a class="confirm" href="####">确定</a></div>'+'</div>';
                this.$dialog=$(tp1);
                $("body").append(this.$dialog);
            },
            bindEvent:function () {
                var _this=this;
                _this.$dialog.find(".cancel").on("click",function () {
                    _this.opts.onCancel();
                    _this.hideDialog();
                });
                _this.$dialog.find(".confirm").on("click",function () {
                    _this.opts.onConfirm();
                    _this.hideDialog();
                });
                _this.$dialog.on("mousedown",function (e) {
                    var $dialog=$(this),
                            evtX=e.pageX-$dialog.offset().left,
                            evtY=e.pageY-$dialog.offset().top;
                    $dialog.addClass("draggable").data("evtPos",{
                        x:evtX,
                        y:evtY
                    })


                });
                $("body").on("mousemove",function (e) {
                    $(".draggable").length && $(".draggable").offset({
                        top:e.pageY-$(".draggable").data("evtPos").y,
                        left:e.pageX-$(".draggable").data("evtPos").x
                    });
                    $("body").on("mouseup",function () {
                        $('.draggable').length && $('.draggable').removeClass('draggable').removeData('evtPos');


                    })
                })

            }

            
        };

        $('#open1').on('click', function() {
            var dialog1 = new Dialog();
            dialog1.open('hello, 这里是饥人谷');
        });
        $('#open2').on('click', function() {
            var dialog2 = new Dialog();
            dialog2.open('<a href="####">这里是链接</a>');
        });
        $('#open3').on('click',function(){
            var dialog3 = new Dialog();
            dialog3.open({
                title: '欢迎来到饥人谷',
                message: "hello",
                isShowCancelBtn: true,
                isShowConfirmBtn: true,
                onCancel: function(){
                    alert('cancel')
                },
                onConfirm: function(){
                    alert('确定');
                }
            });
        });


        var tp1 = '<ul><li>列表1</li><li>列表2</li><li>列表1</li><li>列表1</li></ul>';

        $('#open4').on('click',function(){
            var dialog4 = new Dialog();
            dialog4.open({
                title: '欢迎来到饥人谷',
                message: tp1,
                isShowCancelBtn: true,
                isShowConfirmBtn: true,
                onCancel: function(){
                    alert('cancel')
                },
                onConfirm: function(){
                    alert('确定');
                }
            });
        });

        $('#open5').on('click',function(){
            var dialog5 = new Dialog();
            dialog5.open({
                title: '欢迎来到饥人谷',
                message: "hello",
                isShowCancelBtn: false,
                isShowConfirmBtn: false
            });
        });
        


    </script>



</body>
</html>
(二)、实现如下一个日历组件 【Demo】
  <input class="date-ipt" type="text" placeholder="有初始值" date-init="2016/05/31" />
  <input class="date-ipt" type="text" placeholder="无初始值"  />
  <script>
  // 使用
   $('.date-ipt').datePicker();
  </script>

**本文版权归本人即简书笔名:该账户已被查封 所有,如需转载请注明出处。谢谢! *

相关文章

  • 继承相关基础知识问答

    一、问题 (一)、继承有什么作用? 通过继承可以继承原有函数的一些属性和方法,避免重复定义一些属性和方法,举个例子...

  • js函数相关基础知识问答

    一、问答 (一)函数声明和函数表达式有什么区别 ? 函数声明表示方法的例子: 函数表达式的例子: 那么他们之间有什...

  • 浮动、定位相关基础知识问答

    一、问答 (一)文档流的概念指什么?有哪种方式可以让元素脱离文档流? 文档流指的是将窗口分成一行一行,元素按从左至...

  • 继承相关

    Q:子类继承父类时,重写的变量如何继承?A:重写变量时,变量会在运行时进行类型检查,属于哪个对象就为该对象的变量值...

  • JavaScript的面向对象

    阅读说明:本文档默认已有ES5相关基础知识,包括构造函数、原型、继承等 1.什么是面向对象 面向过程POP VS ...

  • c++ 基础知识回顾 继承 继承的本质就是数据的copy

    c++ 基础知识笔记 继承 什么是继承 继承就是子类继承父类的成员属性以及方法继承的本质就是 数据的复制 是编译器...

  • Android:MVVM的工作原理之创建、销毁、保存、复用

    前言 这里有个基础知识需要了解一下,AppCompatActivity继承了FragmentActivity继承了...

  • 继承相关问题

    问题11:继承有什么作用? 概念:继承就是子类拥有父类的属性和方法, 作用: 父类中是更加通用的属性和方法,通过继...

  • 继承相关问题

    1、继承有什么作用? 在一个基于类的语言(如Java)中,继承(inheritance)提供两个有用的服务。首先,...

  • JVM Java虚拟机相关基础知识问答

    1. 什么情况下会产生栈溢出错误? 首先要明白什么是栈:栈是线程私有的,它的生命周期与线程相同,每个方法在执行的时...

网友评论

      本文标题:继承相关基础知识问答

      本文链接:https://www.haomeiwen.com/subject/zysyuttx.html