【MDNjs笔记】——入门——第三回——对象.构造函数.原型链.继承

对象Object

由属性property(变量)、方法method(函数)组成

 

var objectName = {

  member1Name : member1Value,

  member2Name : member2Value,

  member3Name : member3Value

}

member(成员)的价值是轻易的,

 

一个要是齐所展示之目标为喻为对象的字面量(literal)——手动的描写来目标的内容来创造一个对象。不同为由类实例化一个目标,我们见面当后边学习这种方法。

 

做客对象成员

1.点代表法

目标的名表现呢一个命名空间(namespace),它要写在首先个——当你想拜会对象中的性或方式时,然后是一个点(.),紧接着是您想使拜的品种,标识可以是简单属性之名字(name),或者是频繁组属性的一个子元素,又要是目标的法门调用。如下所示:

person.age

person.interests[1]

person.bio()

 

子命名空间

好就此一个靶来做任何一个对象成员的价值。例如将name成员

 

 

2.括号表示拟

person.age

person.name.first

换成:

person[‘age’]

person[‘name’][‘first’]

当下看起颇像看一个数组的元素,从根本上来说是一样转头事情,你以了事关了价值的名,而无是寻觅引去摘素。难怪对象有时让喻为关联数组(associative
array)
了——对象做了字符串到价值的照,而数组做的凡数字到价值的映射。(值对)

3.点表示法&括号表示法 差异

点表示法只能够领字面量的成员的名字,不收受变量作为名字。

括号表示法一个灵光的地方是它们不仅可动态的去装对象成员的价值,还好动态的错过装成员的名。

如,我们纪念叫用户会当她们的多寡里储存自己定义之值类型,通过简单个input框来输入成员的名和价值,通过以下代码获取用户输入的价值:

var myDataName = nameInput.value

var myDataValue = nameValue.value

俺们好这么将这新的积极分子的讳和值加到person对象里:

person[myDataName] = myDataValue

 

 

 

 

设置对象成员

person.age = 45

person[‘name’][‘last’] = ‘Cratchit’

啊堪创建新成员

person[‘eyes’] = ‘hazel’

person.farewell = function() { alert(“Bye everybody!”) }

 

 

This

重中之重字”this”指向了时代码运行时之目标

 

君一直当使用对象

当我们这样用字符串的方时:

myString.split(‘,’);

而正利用一个字符串实例上可用的道

当您这么看document对象时:

var myDiv = document.createElement(‘div’);var myVideo
= document.querySelector(‘video’);

乃刚好使在管一个Document实例上可用的不二法门。

 

Oop面向对象

Instantiation:实例化

当一个对象实例需要从接近中创造出来时,类的构造函数便见面运作来创造是实例。这种创建对象实例的长河我们誉为实例化-实章对象被类实例化

 

 

 

Inherited:继承(子类继承父类):

 

 

 

自打子类实例化:

 

 

 

 

 

构建函数和目标实例

稍人觉着 JavaScript
不是真的面向对象的语言,比如她没有如许多面向对象的言语一样有用于创建class类的声明。JavaScript
用一栽叫做构建函数的出格函数来定义对象与她的表征。构建函数非常有因此,因为不少情景下您切莫明白实际得有些只对象(实例)。构建函数提供了创而所急需对象(实例)的实用方法,将目标的多少与特征函数按需合并至相应对象。

不像“经典”的面向对象的语言,由构建函数创建的新实例的特色并非全盘复制,而是经过一个名原形链的参考链链接过去的。(see Object
prototypes),所以就不用真的的实例,严格的说道,
Javascript 在对象中使用和另外语言不同之建制共享特征。

创建对象:

1.工厂模式:调用一个创建对象的函数

函数返回值是死目标

得传参数

冗长

function createNewPerson(name) {

  var obj = {};

  obj.name = name;

  obj.greeting = function () {

    alert(‘Hi! I\’m ‘ + this.name + ‘.’);

  }

  return obj;}

var salva = createNewPerson(‘salva’);

salva.name;

salva.greeting();

2.构造函数Constructor(js中的切近)

一个构建函数通常是特别写字母开头,这样方便区分构建函数和一般函数。

使用this关键字

创建对象是要是为此new

而是创很多靶,对象有差命名空间

又迅捷:实际上函数也是当近似吃定义之,而非是以对象实例中

原生构造函数:Object(),Array()等,自动存在被履行环境遭受

 

function Person(name) {

  this.name = name;

  this.greeting = function() {

    alert(‘Hi! I\’m ‘ + this.name + ‘.’);

  };}

var person1 = new Person(‘Bob’);

var person2 = new Person(‘Sarah’);

您本见到页面及发出少数单对象,每一个保存在不等的命名空间里,当您拜它们的习性和方式时,你用运用 person1要么
person2
来调用它们。尽管它有着同样的 name 属性和 greeting() method 它们是个别独立的,所以相互的功用不会见冲。注意她运的凡祥和的 name
值,这也是使用 this
关键字
的因由,它们利用的从实参传入形参的融洽之值,而非是另外的什么价。

片独新的靶子吃创造:

{

  name : ‘Bob’,

  greeting : function() {

    alert(‘Hi! I\’m ‘ + this.name + ‘.’);

  }}

{

  name : ‘Sarah’,

  greeting : function() {

    alert(‘Hi! I\’m ‘ + this.name + ‘.’);

  }}

New之后涉四单步骤:

1创建对象

2用构造函数的作用域给目标(因此this指为此目标)

3行构造函数中的代码

4归新目标

 

3.所以new Object()用配面量创建

var person1 = new Object();

person1.name = ‘Chris’;

person1[‘age’] = 38;

person1.greeting = function() {

  alert(‘Hi! I\’m ‘ + this.name + ‘.’);}

或者:

var person1 = new Object({

  name : ‘Chris’,

  age : 38,

  greeting : function() {

    alert(‘Hi! I\’m ‘ + this.name + ‘.’);

  }});

4.调用Object()的create()方法

可取:基于现有的靶子(person1)创建新对象(克隆)

缺陷:浏览器兼容

var person2 = Object.create(person1);

person2.name

person2.greeting()

5.无限广大的定义对象的艺术:

原型  +  构造函数

原型用来推广方法,构造函数用来放属性

因为

原型适合动态的增长方法,更活,省的在构造函数里面放那么基本上计

原型不合乎添加属性(全局变量不便于访问this)

 

 

 

 

 

 

 

 

 

 

 

靶原型

1.根据原型的语言

JavaScript 常被描述为同样栽基于原型的言语 (prototype-based
language)
——每个对象拥有一个原型对象,对象为那原型为模板、打原型继承方法以及特性。原型对象啊可能持有原型,并从中继承方法及性,一叠一层、以此类推。这种关联常被称作原型链 (prototype chain),它说了胡一个靶见面所有定义在其余对象吃之属性与方。

规范地说,这些性与措施定义在 Object 的组织器函数之上,而不对象实例本身。

当风的 OOP
中,首先定义“类”,此后创建对象实例时,类中定义之拥有属性和方还为复制到实例中。在
JavaScript 中连无这样复制——而是在靶实例和它的构造器里头成立一个一连(作为原型链中的一致节约),以后通过上溯原型链,在构造器中找到这些性与办法:

 

上溯原型链:

事例:定义一个构造器函数:

function Person(first, last, age, gender, interests) {

  // 属性与措施定义

  };

接下来创建一个目标实例:

var person1
= new Person(‘Bob’, ‘Smith’, 32, ‘male’, [‘music’, ‘skiing’]);

 

调用 person1 的 “实际定义在 Object 上之” 方法时,会发什么?比如:

person1.valueOf()

1.浏览器首先检查,person1 对象是不是拥有可用的 valueOf() 方法。

2.若没,则浏览器检查 person1
对象的原型对象(即 Person)是否具备可用之 valueof() 方法。

3.使也尚未,则浏览器检查
Person() 构造器的原型对象(即
Object)是否拥有可用之
valueOf() 方法。Object 具有这个办法,于是该法为调用,

 

即:

办法和总体性没有叫复制到原型链中的其他对象——它们只是经过前述的“上溯原型链”的办法访。

 

 

注意:没有标准的点子用于直走访一个目标的原型对象——原型链中的“连接”被定义在一个内属性遭,在 JavaScript 语言专业中 [[prototype]]
表示(参见 ECMAScript)。然而,大多数现代浏览器还是提供了一个名吧
__proto__ (前后各发2单下划线)的属性,其蕴藉了目标的原型。

若可尝尝输入
person1.__proto__ 和 person1.__proto__.__proto__,看看代码中的原型链是怎么的!

 

在截图中可知看person1的原型是一个目标,包含一个结构器函数Person,包含一个原型属性__proto__,属性值是Object,说明在原型链中Person的齐一级原型是Object。

 

 

 

 

 

 

2.构造函数(类)的prototype 属性:一个对象,在斯目标被定义有能于持续的成员

 

 

当 JavaScript 控制高输入
“person1.”,你见面相,浏览器将根据这个目标的可用之积极分子称进行自动补全。

但其实,Object有再多性与方法,不止上面那些,为什么上面无显得了也??????????

因为

倘吃延续的习性与法举凡概念在
prototype 属性之上的(你可以叫做子命名空间
(sub namespace)
),

——那些以 Object.prototype. 开头的性能,而无仅仅为 Object. 开头的性质,才会为持续。

prototype 属性的值是一个对象,存储在咱想于原型链下游的目标继承的性与道。

 

 

Object.prototype.watch()、Object.prototype.valueOf() 等等成员(可以于控制台数Object.prototype回车查及具有可吃接续的Object的积极分子),适用于任何继承自 Object() 的靶子类型,包括使用构造器创建的新的对象实例。

Object.is()、Object.keys(),以及另不以 prototype 对象内的分子,不见面让“对象实例”或“继承自
Object() 的对象类型”所累。这些方法/属性仅能叫 Object() 构造器自身行使。

 

 

 

 

 

 

3.create方法

 

function Person(first, last, age, gender, interests) {

  

  // 属性与法定义

  

};

var person1=new Person(1,1,1,1,1,);

person2=Object.create(person1);

person2.__proto__;

 

按照MDN上说的,会返回:person1对象

然事实上,

chrome浏览器返回了Person对象

一经firefox浏览器返回了Object对象…………………………………………??此处来疑难

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            

4.constructor属性

每个对象实例都发生constructor属性,指向对象的构造器(构造函数)

控制台输:

function Person(first, last, age, gender, interests) {

  // 属性与措施定义

};

var person1=new Person(1,1,1,1,1,);

person2=Object.create(person1);

person1.constructor

person1.constructor

还见面回Person构造函数:

function Person(first, last, age, gender, interests) {

  // 属性与方式定义

}

 

**故一个靶的组织器属性创建另一个对象:

var person3
= new person1.constructor(‘Karen’, ‘Stephenson’, 26, ‘female’, [‘playing
drums’, ‘mountain climbing’]);

(因为构造器本质就是构造函数,可以透过括号调用,但与一般性函数不同之是,要加new关键字)

 

**constructor还来另外的特性与方,如得有对象构造器的name,length(参数个数),constructor(哈哈constructor的constructor,返回Function构造器,因为构造器本身即是函数来的),

 

 

 

3.改prototype属性,(动态更新原型链)

编辑Person构造函数/构造器      

function Person(first, last, age, gender, interests) {

        this.name = {

          first,

          last

        };

        this.age = age;

        this.gender = gender;

        this.interests = interests;

        this.bio = function() {}

        this.greeting = function() {

          alert(‘Hi! I\’m ‘ + this.name.first + ‘.’);

        };

      };

//为构造器的prototype属性添加新的一个道:

Person.prototype.farewell = function() {

  alert(this.name.first + ‘ has left the building. Bye for now!’);

}

//控制台输

person1.farewell();

 

卿见面看出同样长长的警告信息,其中还出示了构造器中定义之人名;这十分有因此。但再主要之是,整条继承链动态地换代了,别由此构造器创建的对象实例都自动获取了这法。

 

当即说明了以前叙的原型链模型。这种持续模型下,上游对象的方无会见复制到下游的对象实例中;下游对象自我虽然没有概念这些方法,但浏览器会通过达成溯原型链、从上游对象中找到她。这种持续模型提供了一个强大而可扩大的效用体系。

 

 

 

注意,给prototype增加属性一般是加方法

或追加常属性(无法改变的特性constant property)

 

因为

Person.prototype.fullName = this.name.first + ‘ ‘ + this.name.last;

这么加会出错,,,this指代的凡时实践环境的大局范围

 

只要加以计

Person.prototype.farewell = function() {

  alert(this.name.first + ‘ has left the building. Bye for now!’);}

诸如此类即便会见成,因为这晓词位于函数范围外,从而能够成功地变为对象实例范围。(是目标调用这个办法)

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

继承

前说的prototype继承,是依赖目标实例能够访问:构造器中prototype属性中的方式。

此间说之累是 构造器 到 构造器 的继承

 

1.

//Person构造器:

function Person(first, last, age, gender, interests) {

  this.name = {

    first,

    last

  };

  this.age = age;

  this.gender = gender;

  this.interests = interests;

};

//Teacher构造器:

function Teacher(first, last, age, gender, interests, subject) {

  Person.call(this, first, last, age, gender, interests);

  this.subject = subject;

}

Teacher构造器从Person构造器继承了有着属性,又新增了一个subject属性。

这样很**高效**

 

 

 

 

call()函数。基本上,这个函数允许你调用一个在这个文件里 变处定义的函数。第一独参数指明了以您运行是函数时想对“this”指定的价值,也就是说,你可以再指定你调用的函数里拥有“this”指向的靶子。其他的变量指明了有目标函数运行时受之参数。

(调用 同文件 别的函数 ,能更改/指定 this指向的值 )

 

 

 

2.从Person()继承prototype

方的运call的方,让Teacher()继承到了Person()的持有属性,但是这Teacher()只发生一个缺损的prototype属性(本质也是一个对象),如何吃Teacher()从Person()的原型属性之中继续方法也?

Teacher.prototype = Object.create(Person.prototype);

嘿!用旧**create**

因而create()函数来以Person.prototype这个目标克隆给Teacher.prototype。

因为prototype属性本质也是一个对象,所以可以就此create的法门去克隆一个靶吃Person.prototype。

 

 

 

3.设置Teacher()的constructor

直接从Person()继承,见面要Teacher()的prototype属性中的constructor属性指向Person(),也就是说由Teacher()创建的目标实例,查这个目标的构造器时,返回的是Person(), 这是由我们生成Teacher()的方式导致的。(这首 Stack Overflow post  https://stackoverflow.com/questions/8453887/why-is-it-necessary-to-set-the-prototype-constructor  文章会报您详细的原理)

 

 

即说不定会化大非常之问题,所以我们得以那个对安装——你得回去源代码,在底下加上这一行代码来缓解:

 

Teacher.prototype.constructor = Teacher;