美文网首页
js面向对象

js面向对象

作者: 岛在深海处 | 来源:发表于2018-08-07 14:52 被阅读0次
1.函数的原型链(__ proto__,prototype,constructor )
  • 函数的原型(prototype),包含2个默认属性:{constructor : ... , __ proto__:window.Object.prototype}
    函数名.prototype.arg1 = "value_arg1" 这样添加后 arg1将与constructor,__proto __平级
    函数名.arg2 = "value_arg2" 这样添加后,arg2将被添加到constructor中。

  • 函数的实例,包含一个默认属性{__ proto__ : 函数的原型(prototype)}
    当访问一个函数的实例的属性或方法的时候,浏览器会先在这个函数的实例本身查找有没有这个属性或方法,没有就在它的__ proto__(函数的原型)中查找,如果还没有就继续往__ proto__的__ proto__中查找直到__ proto__ === window.Object.prototype

注意:访问函数实例的属性,不会去constructor中查找,即如果函数名.arg2,函数实例.arg2返回的是undefined,因为constructor也是函数实例的一个属性,且这个属性等于函数本身。

this 关键字并不是指向当前对象的原型对象,this指向的是当前对象的一个实例。

this.属性实际上是把属性实际上是把属性或方法拷贝到每个实例中,有多少个实例就有多少份,而prototype则是通过引用指向,所以在内存中只有一份

注意:一般属性是定义在函数体中,用this. 这样子类和实例都能拿到,同样也都能改变,每个实例有自己的一份。而方法则定义在prototype中,每个实例如果想有自己独立的方法,利用原型链优先查找原则"重写该方法"

函数是对象,只有函数对象有原型,而函数的实例是没有原型的,只有个__ proto__是指向函数的原型。

必须重申,原型链中的方法和属性没有被复制到其他对象——它们被访问需要通过前面所说的“原型链”的方式。上游对象的方法不会复制到下游的对象实例中;下游对象本身虽然没有定义这些方法,但浏览器会通过上溯原型链、从上游对象中找到它们

例如:Array的prototype属性定义了一些方法,所有Array对象都能使用。
如果Array.直接定义一些属性,则Array的实例对象不能直接返回到。

函数的原型中的constructor === 函数本身,即:
Person.prototype.constructor===Person

创建对象一般是在构造器(函数体)中定义属性、在 prototype 属性上定义方法

// 构造器及其属性定义

function Test(a,b,c,d) {
  // 属性定义
    this.a = a
};

// 定义第一个方法

Test.prototype.x = function () { ... }

// 定义第二个方法

Test.prototype.y = function () { ... }

// 等等……

上面代码中的this.a = a 中的this实际上是Test.call(this, "a", "b", "c", "d")方法传进去的。

2.创建对象
  • 1> var childObj = Object.create(supObj) 传入一个原型对象,并创建一个基于该原型的新对象,新对象的__ proto__ === supObj

var newObj = Object.create(supObj)实际上执行的是(伪代码):

function create(){
    newObj.__ proto__ = supObj;
    return newObj
}

childObj重写父类supObj的属性后,该属性的值跟supObj中的该属性值得变化无关。如果没有重写则会随supObj的变化而变化。

  • 2> 构造函数的方式:
function Student(name) {
    this.name = name;
    this.hello = function () {
        alert('Hello, ' + this.name + '!');
    }
}
var xiaoming = new Student('小明');
xiaoming.name; // '小明'
xiaoming.hello(); // Hello, 小明!

注意:构造函数千万别忘记new。在strict模式下,this.name = name将报错,因为this绑定为undefined,在非strict模式下,this.name = name不报错,因为this绑定为window,于是无意间创建了全局变量name,并且返回undefined,这个结果更糟糕。

new 函数的实现原理:
function trivialNew(constructor, ...args) {
    var o = {}; // 创建一个对象
    o = Object.create(constructor.prototype); //设置实例的__ proto__

    constructor.call(o, ...args);//传this进去复制构造方法中的函数和变量。
    return o;
}

需要注意的是create()方法与call()方法的顺序,执行create()方法会将o实例的所有非constructor.prototype属性清空。理由如下Object.create()实现原理:

if (!Object.create) {
    Object.create = function (o) {
    function F() {}  //定义了一个隐式的构造函数
    F.prototype = o;
    return new F();  //其实还是通过new来实现的
    };
  }

3> 直接定义创建

  var Chinese = {
    nation:'中国'
  };

Chinese相当与一个实例。

3.继承
  • 1>
function inherits(Child, Parent) {
    var F = function () {};
    F.prototype = Parent.prototype;
    Child.prototype = new F();

    Child.prototype.constructor = Child;
}

记得在子类中调用父类构造函数Parent.call(this, props),确保子类能继承父类函数体(构造器函数中)中的属性

inherits上面三行代码跟Object.create()方法一样实际效果都是将Child.prototype的
__ proto__指向Parent.prototype,这样会改变Child构造器指向,使之与Child关联,所以要执行 Child.prototype.constructor = Child;这段代码。

最后来一个ES6的class创建对象。。。。
class Student {
    constructor(name) {
        this.name = name;
    }

    hello() {
        alert('Hello, ' + this.name + '!');
    }
}
var xiaoming = new Student('小明');
xiaoming.hello();
class继承。。。。
class PrimaryStudent extends Student {
    constructor(name, grade) {
        super(name); // 记得用super调用父类的构造方法!
        this.grade = grade;
    }

    myGrade() {
        alert('I am at grade ' + this.grade);
    }
}

总结

三种定义对象的属性的方式

1.定义在造器函数中的,this.x = x 在内置的浏览器代码中,它们是可用于对象实例的成员,通常通过使用new关键字调用构造函数来创建

2.那些直接在构造函数上定义、仅在构造函数上可用的。这些通常仅在内置的浏览器对象中可用,并通过被直接链接到构造函数而不是实例来识别。 例如:直接用函数名.属性

3.那些在构造函数原型上定义、由所有实例和对象类继承的。这些包括在构造函数的原型属性上定义的任何成员,如myConstructor.prototype.x()。

相关文章

  • JS面向对象精要(二)_函数

    JS面向对象精要(一)_原始类型和引用类型JS面向对象精要(二)_函数JS面向对象精要(三)_理解对象JS面向对象...

  • JS面向对象精要(三)_理解对象

    JS面向对象精要(一)_原始类型和引用类型JS面向对象精要(二)_函数JS面向对象精要(三)_理解对象JS面向对象...

  • JS面向对象精要(四)_构造函数和原型对象

    JS面向对象精要(一)_原始类型和引用类型JS面向对象精要(二)_函数JS面向对象精要(三)_理解对象JS面向对象...

  • JS面向对象精要(五)_继承

    JS面向对象精要(一)_原始类型和引用类型JS面向对象精要(二)_函数JS面向对象精要(三)_理解对象JS面向对象...

  • js 面向对象和面向过程

    js 面向对象和面向过程

  • 面向对象OOP--JS

    作者:烨竹 JS面向对象简介 JS名言:万物皆对象 JS面向对象比PHP简单很多;因为JS中没有class关键字,...

  • JavaScript笔记(一)

    一、面向对象面向过程的区别 1、什么是js对象 js对象:属性和方法的集合,js所有数据都可以看成对象...

  • JS面向对象

    JS面向对象入门 1、面向对象语言概念面向对象语言主要包括 类、对象、封装、多肽。2、面向对象的编程思想面向过程思...

  • 2018-01-18

    js中的面向对象核心 js是基于对象的编程语言,在后面的学习中我们通过一种模式使其转化成为面向对象的语言。js面向...

  • 浅谈JS中的面向对象

    浅谈JS中的面向对象 本文主要说说本人在JS中对面向对象的理解。 计算机编程语言主要分为面向过程式编程和面向对象式...

网友评论

      本文标题:js面向对象

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