web 原型链与对象

原型链类

1、创建对象有几种方法

 2、原型、构造函数、实例、原型链的概念

3、instanceof的原理

4、new运算符

创建对象有几种方法

字面量的方法   构造函数的方法  Object.create的方法

原型、构造函数、实例、原型链的概念

 

构造函数:只有是new后面的函数,它就不是一个普通的函数,它就是一个构造函数,任何一个函数只要被new使用了,都可以是构造函数

 函数都有一个prototype属性,在声明一个函数的时候,js就会自动给一个prototype属性,prototype指的是原型对象,原型对象的constructor是声明的那个函数

 原型链是通过什么往上查找呢?通过__proto__

任何一个实例化的对象,通过原型链找到它上面的原型对象,这个原型对象上面的方法和属性是它的实例对象所共用的。这就是原型链的基本原理

 

M = function (name) {
this.name = name
this.say = function () {
console.log('say hi')
}
}
M.prototype.say = function () {
console.log('say hi')
}
var o1 = new M('o1')
上述代码中,在构造函数中写的方法,和在原型对象上写的方法的区别:
构造函数中写的方法在每次实例化对象的时候都会被执行一次,会比较占内存,而在原型对象上面写的方法,是可以让实例对象通过原型链进行继承的

 只有实例才有__proto__属性,但是会发现上述的M也有__proto__属性,这是因为函数其实它也是一个对象,发现M.__proto ==function.prototype,就是说M的构造函数是function

 instanceof的原理

instanceof 判断实例是否是某个构造函数的实例

比如:o1.instanceof == M // true

  o1.instanceof == Object //true

只要是在o1的原型链上的构造函数,o1都可以instanceof

比如 A继承了B,B继承了C,那么A的实例a1 a1.instanceof === B | A | C都是返回true

那么如果知道a1是通过谁来进行实例化的呢?这得用constructor

a1.__proto__.contractor === A // true

a1.__proto__.contractor === B // false

new 运算符

面向对象类

  类与实例

    类的声明

    生成实例

  类与继承

    如何实现继承

    继承的几种方式

 

类与实例

/**
* 类的声明
*/
var Animal = function () {
this.name = 'Animal';
};

/**
* es6中class的声明
*/
class Animal2 {
constructor () {
this.name = 'Animal2';
}
}

/**
* 实例化
*/
console.log(new Animal(), new Animal2());

类与继承

 

/**
* 借助构造函数实现继承

这种方法只能部分继承,继承不了原型对象上的方法和属性

call:将父级函数运行的this指向子类函数
*/
function Parent1 () {
this.name = 'parent1';
}
Parent1.prototype.say = function () {

};
function Child1 () {
Parent1.call(this);
this.type = 'child1';
}
console.log(new Child1(), new Child1().say());

/**
* 借助原型链实现继承

这种方法的缺点:如果其中一个实例改变了原型对象上的一个方法,则其他的实例的方法都会被改变,因为所有实例都是继承了一个原型链上的方法
*/
function Parent2 () {
this.name = 'parent2';
this.play = [1, 2, 3];
}
function Child2 () {
this.type = 'child2';
}
Child2.prototype = new Parent2();

var s1 = new Child2();
var s2 = new Child2();
console.log(s1.play, s2.play);
s1.play.push(4);

/**
* 组合方式

这种方式的缺点就是:父级的构造函数执行了两次,

如果把play写到prototype中,实例中的一个对象改变此方法,则另外的对象的此方法也跟着改变
*/
function Parent3 () {
this.name = 'parent3';
this.play = [1, 2, 3];
}
function Child3 () {
Parent3.call(this);
this.type = 'child3';
}
Child3.prototype = new Parent3(); // 构造函数执行了一次
var s3 = new Child3();// 构造函数又执行了一次
var s4 = new Child3();
s3.play.push(4);
console.log(s3.play, s4.play);

/**
* 组合继承的优化1

Child4.prototype = Parent4.prototype;此步把child4的原型对象和parent4的原型对象是指向了同一个,当new chlid4()的时候,无法区分这个实例的构造函数是chlid4还是parent4
* @type {String}
*/
function Parent4 () {
this.name = 'parent4';
this.play = [1, 2, 3];
}
function Child4 () {
Parent4.call(this);
this.type = 'child4';
}
Child4.prototype = Parent4.prototype;
var s5 = new Child4();
var s6 = new Child4();
console.log(s5, s6);

console.log(s5 instanceof Child4, s5 instanceof Parent4);
console.log(s5.constructor);

/**
* 组合继承的优化2

Object.create(Parent5.prototype) 首先创造一个空的对象,这个对象的原型对象继承了parent5.prototype的原型对象,这就能区分了child5的构造函数了

Object.create(参数)这个方法创建的对象的原型对象就是它的参数
*/
function Parent5 () {
this.name = 'parent5';
this.play = [1, 2, 3];
}
function Child5 () {
Parent5.call(this);
this.type = 'child5';
}
Child5.prototype = Object.create(Parent5.prototype);

Child5.prototype.constractor = Child5

 

posted @ 2018-03-02 15:00  ls-lansy  阅读(173)  评论(0编辑  收藏  举报