原型和原型链

题目:javascript

  1.如何正确判断一个变量是数组html

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

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

知识点:数组

  构造函数函数

  构造函数-扩展this

  原型规则spa

  原型链prototype

  instanceofcode

 

建立对象的几种方法:

  1. 字面量方法

    var o1 = {name:'o1'};

  2. new Object():

    var o2 = new Object({name:'o2'})

  3. 构造函数:

    var M = function(name){this.name = name};

    var o3 = new M('o3');

  4. Object.create():

    var f = {name: 'o4'};

    var o4 = Object.create(f);

构造函数

function Foo(name,age){
  this.name = name;
  this.age = age;
  this.class = 'class-1';
}

 

构造函数的扩展

  var a = {};其实就是 var a = new Object()的语法糖

  var a = []; 其实就是var a = new Array()语法糖

  function Foo(){...};其实就是 var Foo = new Function(){...}

 

原型规则

   1. 全部的引用类型(数组、对象、函数),都具备对象特性,能够自由扩展属性

var obj = {};obj.a = 100;
var arr =[];arr.a = 100;
function fn(){}; fn.a = 100;

   2. 全部的引用类型(数组、对象、函数),都有一个__proto__隐式原型属性

var obj = {};obj.a = 100;
var arr =[];arr.a = 100;
function fn(){}; fn.a = 100;
		
console.log(obj.__proto__);
console.log(arr.__proto__);
console.log(fn.__proto__);

   3. 全部函数,都具备一个prototype显示原型属性

function fn(){}; fn.a = 100;
console.log(fn.prototype);

   4. 全部引用类型(数组、对象、函数)的__proto__属性值 指向它的构造函数的 prototype属性值

var obj = {};
var arr =[];
function fn(){};

console.log(obj.__proto__ === Object.prototype)//true
console.log(arr.__proto__ === Array.prototype)//true
console.log(fn.__proto__ === Function.prototype) //true

   5. 当获取一个对象的某个属性时,若是这个对象自己没有这个属性,那么会去它的__proto__(即构造函数的prototype)中寻找

function Foo(name){
  this.name = name ;      
}
Foo.prototype.alerName = function(){
  alert(this.name);  
}

var f = new Foo('zhangsan');
f.printName = function(){
  console.log(this.name);  
}

f.printName();
f.alertName();//f自己没有alertName,但Foo.prototype存在。因此能够找到并执行

 

原型链

  简单理解就是:原型对象组成的链,一直经过__proto__属性向上找,直到找到Object的原型时结束:

function Foo(name,age){
    this.name = name;
}
Foo.prototype.alertName = function(){
    alert(this.name);
}
var f = new Foo('zhangsan');
f.printName = function(){
    console.log(this.name);
}
f.printName();
f.alertName();
f.toString();//要去f.__proto__.__proto__中查找

 以上面代码为例

 1. f没有alertName方法,因此会去f.__proto__上去查找,由于f.__proto__ === Foo.prototype ,而Foo.prototype上有该方法。因此f.alertName()能够找到并被执行

 2. f没有toString方法,因此会先去f.__proto__上去查找,Foo.prototype上也没有改方法;因此会继续去f.__proto__.__proto__上去查找(f.__proto__.__proto__ === Foo.prototype.__proto__ === Object.prototype),即Object.prototype上查找,因此f.toString()能够找到并执行

  3.Object.prototype也一样有__proto__属性,只不过有点特殊,为null

  咱们把__proto__串联起来,直到Object.prototype.__proto__为止的链叫作原型链

 下面用一张图来表示:

  

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

  经过代码来解释

var M = function (name) { this.name = name; };
var o1 = new M('test'); console.log(M.prototype === o1.__proto__);//true console.log(M.prototype.constructor === M);//true

  1.实例是经过new 一个构造函数生成的,即代码中 o1就是实例,M就是构造函数。

  2.构造函数的prototype属性指向的是原型(或者说原型对象)。即代码中 M.prototype === o1.__proto__

  3. 实例的__proto__属性指向的也是原型(或者说原型对象)。即 代码中 M.prototype === o1.__proto__

  4. 原型(或者说原型对象)对象的constructor指向的是构造函数。即代码中 M.prototype.constructor === M

原型链继承的例子

  题目二解答:写一个原型链继承的例子?

//封装DOM查询 相似jquery用法
function Elem(id){
	this.elem = document.getElementById(id);
}
//jquery中 html 方法
Elem.prototype.html = function(val){
	var elem = this.elem;
	if (val){ //设置html结构
		elem.innerHTML = val;
		return this; //链式操做
	}else{//获取html结构
		return elem.innerHTML;
	}
}
//事件
Elem.prototype.on = function(type,fn){
	var elem = this.elem;
	elem.addEventListener(type,fn,false);
	return this; //链式调用
}

 

  调用:

var div1 = new Elem('div1')

div1.on('click',function(){
	alert('clicked');
})

div1.html('点击');

console.log(div1.html());

  

 

instanceof 和 constructor

  检测某个对象是否是另外一个对象的实例能够用constructor 或者instanceof

  1. instanceof的原理是:判断实例对象的__proto__和生成该实例的构造函数的prototype是否是引用的同一个地址(或者说是否是相等),若是是返回ture;若是是原型链上向上找的构造函数一样返回true。

  经过代码来解释:    

var M = function (name) { this.name = name; };
var o1 = new M('test');
console.log(o1 instanceof M) //true
console.log(o1 instanceof Object) //true

    由于o1.__proto__ === M.prototype 因此 o1 instanceof M 返回为true;

    由于 M.prototype.__proto__ === Object.prototype ,即Object是原型链上的构造函数,因此返回为true.

  2. constructor是:判断实例是由哪一个构造函数生成的。

  经过代码来解释:

var M = function (name) { this.name = name; };
var o1 = new M('test');
console.log(o1.__proto__.constructor === M) //true
console.log(o1.__proto__.constructor === Object) //false

 题目一解答:如何准确判断一个变量是数组类型?

  用instanceof来判断一个变量是不是数组,代码示例:

var arr =[];
arr.instanceof Array //true;
typeof arr //object

  

new 运算符的原理

  当咱们new一个实例对象时,JS执行时在内部作了不少工做,下面用伪代码模拟其工做流程:

new Foo('name') => {
    var obj = {}; //建立一个空对象
obj.__proto__ = Foo.prototype; //把obj的__proto__指向构造函数的原型对象(Foo.prototype),此时创建了obj的原型链 obj->Foo.prototype -> Object.prototype
   var result = Foo.call(obj,'name');//改变this指向 

  return typeof result === 'object'? result : obj //判断result类型是否是对象,是返回result,不是返回obj
}

     1)建立一个空对象obj,该对象obj继承构造函数的原型(Foo.prototype)

    2) 将这个空对象的__proto__指向构造函数Foo的原型对象

    3)构造函数Foo被执行,在执行的时候,相应的参数会被传入,同时上下文(this)会被替换成obj

    4) 考察第三步的返回值result,若是无返回值或者返回一个非对象的值,则将obj做为新对象返回;不然将result做为新对象返回

  题目三解答:描述 new 一个对象的过程?

    1. 首先建立一个新对象{};

    2. 将构函数的做用域赋给新的对象向(所以 this指向了这个新建立的对象);

    3. 执行构造函数中的代码(为这个新对象添加属性);

    4. 返回这个新对象

相关文章
相关标签/搜索