原型和原型链

题目(答案见每题下方空白处)

  1.如何准确判断一个变量是数组类型

  用instanceof Array,返回为true就说明是

  2.写一个原型链继承的例子

function Animal(){
    this.eat = function(){
        console.log('animal eat');
    }
}
function Cat(){
    this.say = function(){
        console.log('cat miao');
    }
}
Cat.prototype = new Animal();
       
var mimi = new Cat();
mimi.eat();
原型继承1
function Elem(id){
    this.elem = document.getElementById(id);
}
Elem.prototype.html = function(val){
    var elem = this.elem;
    if(val){
        elem.innerHTML = val;
        return this;//为了链式操作
    }
    else{
        return elem.innerHTML;
    }
}
Elem.prototype.on = function(type,fn){
    var elem = this.elem;
    elem.addEventListener(type,fn);
    return this;//为了链式调用
}

var div1 = new Elem('detail-page');
div1.html('<p>hello imooc</p>').on('click',function(){
    alert('clicked');
}).html('<p>javascript</p>');
原型继承2(实际开发会用)

 

  3.描述new一个对象的过程

  分三步,假定该对象名为xm,则先是xm={},即xm为一个空对象,然后xm.__proto__ = object.prototype,最后调用call方法,xm.call()

  或者另一种理解分四步,先是创建一个新对象,然后this指向这个新对象,之后执行代码,对this赋值,最后返回this

  4.zepto(或其他框架)源码中如何使用原型链

   (未完待续)

 

知识点

构造函数

  先举一个构造函数的例子

  

  构造函数一般函数名开头大写(约定俗成),函数内部用this指向来给对象赋值

  整个过程如下:

  1.this指向一个空对象

  2.通过构造函数里的赋值,this得到众多属性值,赋值完成后,默认返回this

  3.把这个对象赋值给f(也就是f.call())

构造函数扩展

  var a = {}为var a = new Object()的语法糖(即功能没有改变,只是改变了语法,使得代码更易阅读

  var a = []为var a = new Array()的语法糖

  function Foo(){}为var Foo = new Function()的语法糖

原型规则

  1.所有的引用类型都有对象特性,即可以自由扩展属性(null除外)

  

  2.所有引用类型都有一个__proto__属性(隐式原型),属性值为一个普通对象

  

  (这里一个问题,object的__proto用instanceof判断,返回的是false)

  3.所有的函数都有一个prototype属性(显式原型),属性值为一个普通对象

  

  4.所有引用类型的__proto__属性值指向其构造函数的prototype属性值

  

  5.当试图得到一个对象的某个属性时,如果这个对象本身没有这个属性,就会去其__proto__(即其构造函数的prototype)中寻找(原型链的原理)

  

  这里alertName这个属性(方法)在f实例中没有,所以就去其原型上查找,也就是Foo.prototype上查找,最后调用

其他注意点

  如果遍历对象上的属性,for-in会遍历其对象本身以及原型上的所有属性(输出的是属性名

  

  而for-of只会遍历其对象本身的属性(但必须是可遍历的,即iterable

  如果需要限制遍历对象本身的属性,则用Object对象的hasOwnProperty方法(for-of方法在新浏览器中基本解决了这一问题,但为了以防万一,还是加上为好)

  

原型链

  每个函数都有一个prototype属性,而所有引用类型都有一个__proto__属性,指向其构造函数的prototype属性

  这样一来就形成了一条以对象__proto__属性(隐式属性)和函数prototype属性(显式属性)构成的一条无形的链子,即原型链

  

  但需要注意的是,Object这个构造函数的显式属性隐式属性null(即Object.prototype.__proto__为null)

  这是JS的一个机制,为了避免原型链的死循环

instanceof

  该方法用来判断引用类型的变量属于哪个构造函数

  实际上的判断逻辑为原型链,也就是该实例的__proto__属性层层往上,能否对应上构造函数的prototype属性

  也就可以回答了为什么Object实例的__proto__属性不是Object的实例(obj.__proto__.__proto__实际上为Object.prototype.__proto__,指向null,自然不等于Object.prototype)

posted @ 2019-09-20 21:57  且听风吟720  阅读(126)  评论(0编辑  收藏  举报