A能使用B的方法和属性, 在写入访问器属性的时

前端基础进级(9):详解面向对象、构造函数、原型与原型链

2017/04/02 · JavaScript · 1 评论 · 原型, 原型链, 构造函数, 面向对象

原稿出处: 波同学   

图片 1

.

假设要本人总括一下读书前端以来小编蒙受了何等瓶颈,那么面向对象一定是首先个坚决想到的。即使小编昨日对此面向对象有了一些的理解,不过那时候的这种似懂非懂的优伤,依旧日思夜想。

为了救助我们能够越来越直观的读书和理解面向对象,作者会用尽量轻巧易懂的陈说来彰显面向对象的有关文化。况兼也计划了一部分实用的事例协理大家越来越高效的调控面向对象的真谛。

  • jQuery的面向对象达成
  • 装进拖拽
  • 简易版运动框架封装

那只怕会花一点光阴,可是却值得期望。所以要是有意思味的意中人能够来简书和公众号关切本人。

而那篇小说重要来聊一聊关于面向对象的一对首要的功底。

Object类型是JavaScript中利用最多的一连串型。创造Object实例的格局有多样,接下去一一列举。

javascript中的种种对象都有三个停放的习性prototype,Javascript中目的的prototype属性的解说是:重临对象类型原型的援引。意思是是prototype属性保存着对另一个JavaScript对象的引用,这么些指标作为当前指标的父对象。

JavaScript中原型和原型链详解

 这篇小说首要介绍了JavaScript中原型和原型链详解,本文讲明了私家变量和函数、静态变量和函数、实例变量和函数、原型和原型链的基本概念,需求的对象能够参照下

 

 

javascript中的每种对象皆有四个放到的品质prototype,Javascript中目的的prototype属性的解释是:再次回到对象类型原型的引用。意思是是prototype属性保存着对另三个JavaScript对象的引用,那一个目的作为当前目的的父对象。

复制代码 代码如下:

A.prototype = new B();
理解prototype不应把它和接二连三混淆。A的prototype为B的叁个实例,能够明白A将B中的方法和属性全体仿制了三次。A能接纳B的主意和质量。这里重申的是仿造并非继续。能够出现这种状态:A的prototype是B的实例,同期B的prototype也是A的实例。

 

接轨看下边包车型地铁深入分析:

村办变量和函数

在函数内部定义的变量和函数,纵然不对外提供接口,外界是无法访谈到的,也正是该函数的村办的变量和函数。

复制代码 代码如下:

<script type="text/javascript">
function Box(){
var color = "blue";//私有变量
var fn = function() //私有函数
{

 

}
}
</script>

诸有此类在函数对象博克斯外界无法访问变量color和fn,他们就变成私有的了:

复制代码 代码如下:

var obj = new Box();
alert(obj.color);//弹出 undefined
alert(obj.fn);//同上

 

静态变量和函数

当定义八个函数后经过点号 “.”为其拉长的习性和函数,通过对象自己仍可以访谈获得,可是其实例却访谈不到,那样的变量和函数分别被喻为静态变量和静态函数。

 

复制代码 代码如下:

<script type="text/javascript">
function Obj(){};

 

Obj.num = 72;//静态变量
Obj.fn = function() //静态函数
{

}

alert(Obj.num);//72
alert(typeof Obj.fn)//function

var t = new Obj();
alert(t.name);//undefined
alert(typeof t.fn);//undefined
</script>

 

实例变量和函数

在面向对象编制程序中除去有的库函数大家依旧期望在对象定义的时候还要定义一些质量和办法,实例化后得以访谈,js也能造成这样

复制代码 代码如下:

<script type="text/javascript">
function Box(){
this.a=[]; //实例变量
this.fn=function(){ //实例方法

 

}
}

console.log(typeof Box.a); //undefined
console.log(typeof Box.fn); //undefined

var box=new Box();
console.log(typeof box.a); //object
console.log(typeof box.fn); //function
</script>

 

为实例变量和情势增添新的不二等秘书技和品质

复制代码 代码如下:

<script type="text/javascript">
function Box(){
this.a=[]; //实例变量
this.fn=function(){ //实例方法

 

}
}

var box1=new Box();
box1.a.push(1);
box1.fn={};
console.log(box1.a); //[1]
console.log(typeof box1.fn); //object

var box2=new Box();
console.log(box2.a); //[]
console.log(typeof box2.fn); //function
</script>

 

在box第11中学修改了a和fn,而在box第22中学尚无改造,由于数组和函数都是指标,是援引类型,那就证实box第11中学的属性和办法与box2中的属性与措施就算同名但却不是一个援引,而是对Box对象定义的品质和措施的多少个复制。

本条对品质来讲未有何难题,可是对于艺术来讲问题就不小了,因为方法都是在做完全等同的功能,可是却又两份复制,若是二个函数对象有上千和实例方法,那么它的种种实例都要维持一份上千个措施的复制,这明显是不得法的,那可咋做呢,prototype应时而生。

基本概念

大家成立的种种函数都有七个prototype属性,那脾本性是二个指南针,指向二个指标,这几个目的的用处是富含能够由特定类型的有着实例分享的属性和措施。那么,prototype正是透过调用构造函数而创办的百般目的实例的原型对象。

运用原型的功利是足以让对象实例分享它所满含的本性和方法。也等于说,不必在构造函数中增加定义对象音讯,而是能够一直将那一个音讯加多到原型中。使用构造函数的要害难点正是每一个方法都要在各种实例中开创一回。

在JavaScript中,一共有三种等级次序的值,原始值和目标值。每一个对象都有六个中间属性 prototype ,大家层出不穷称为原型。原型的值能够是叁个指标,也得以是null。如若它的值是多个对象,则那些目的也一定有友好的原型。那样就变成了一条线性的链,大家称为原型链。

含义

函数能够用来作为构造函数来使用。别的独有函数才有prototype属性并且可以访谈到,可是对象实例不有所该属性,唯有两在这之中间的不行访谈的__proto__属性。__proto__是目的中贰个对准相关原型的暧昧链接。遵照职业,__proto__是不对伯公开的,也正是说是个个体属性,可是Firefox的引擎将他暴光了出来改成了三个共有的习性,大家得以对外访问和设置。

复制代码 代码如下:

<script type="text/javascript">
var Browser = function(){};
Browser.prototype.run = function(){
alert("I'm Gecko,a kernel of firefox");
}

 

var Bro = new Browser();
Bro.run();
</script>

 

当大家调用Bro.run()方法时,由于Bro中未有这一个格局,所以,他就能去她的__proto__中去找,也正是Browser.prototype,所以最终实行了该run()方法。(在此处,函数首字母大写的都表示构造函数,以用来区分普通函数)

当调用构造函数创制二个实例的时候,实例之大校包含贰个之中指针(__proto__)指向构造函数的prototype,这么些一而再存在于实例和构造函数的prototype之间,并非实例与构造函数之间。

复制代码 代码如下:

<script type="text/javascript">
function Person(name){ //构造函数
this.name=name;
}

 

Person.prototype.printName=function() //原型对象
{
alert(this.name);
}

var person1=new Person('Byron');//实例化对象
console.log(person1.__proto__);//Person
console.log(person1.constructor);//本人尝试看会是怎么着啊
console.log(Person.prototype);//指向原型对象Person
var person2=new Person('Frank');
</script>

Person的实例person第11中学满含了name属性,同期自动生成二个__proto__质量,该属性指向Person的prototype,能够访谈到prototype钦赐义的printName方法,大约正是其同样子的:

 

图片 2

各类JavaScript函数都有prototype属性,这本个性引用了二个指标,这么些指标便是原型对象。原型对象起始化的时候是空的,我们能够在里头自定义任何性质和措施,那个主意和性质都将被该构造函数所创办的指标承继。

那么,今后主题素材来了。构造函数、实例和原型对象三者之间有怎么着关联吗?

构造函数、实例和原型对象的分别

实例就是经过构造函数创建的。实例一创制出来就具备constructor属性(指向构造函数)和__proto__属性(指向原型对象),

构造函数中有贰个prototype属性,这一个天性是一个指针,指向它的原型对象。

原型对象内部也会有二个指针(constructor属性)指向构造函数:Person.prototype.constructor = Person;

实例能够访谈原型对象上定义的习性和方法。

在此间person1和person2正是实例,prototype是他们的原型对象。

再举个栗子:

复制代码 代码如下:

<script type="text/javascript">
function Animal(name) //积存构造函数
{
this.name = name;//设置对象属性
}

 

Animal.prototype.behavior = function() //给基类构造函数的prototype增加behavior方法
{
alert("this is a "+this.name);
}

var Dog = new Animal("dog");//创建Dog对象
var Cat = new Animal("cat");//创建Cat对象

Dog.behavior();//通过Dog对象直接调用behavior方法
Cat.behavior();//output "this is a cat"

alert(Dog.behavior==Cat.behavior);//output true;
</script>

 

能够从程序运营结果来看,构造函数的prototype上定义的措施确实能够透过对象直接调用到,何况代码是分享的。(能够试一下将Animal.prototype.behavior 中的prototype属性去掉,看看还是能还是不能运作。)在这边,prototype属性指向Animal对象。

数组对象实例

再看个数组对象的实例。当大家创立出array1那些目的的时候,array1实际在Javascript引擎中的对象模型如下:

复制代码 代码如下:

var array1 = [1,2,3];

 

图片 3

array1对象具有五个length属性值为3,不过大家能够因而如下的办法来为array1增美成分:

复制代码 代码如下:

array1.push(4);
push那一个主意来自于array1的__proto__成员指向对象的二个情势(Array.prototye.push())。就是因为具有的数组对象(通过[]来创立的)都富含有三个针对同一个富有push,reverse等艺术对象(Array.prototype)的__proto__分子,才使得这一个数组对象能够使用push,reverse等措施。

 

函数对象实例

复制代码 代码如下:

function Base() {
this.id = "base"
}

 

图片 4

 

复制代码 代码如下:

var obj = new Base();
与此相类似代码的结果是什么样,我们在Javascript引擎中看看的对象模型是:

 

图片 5

new操作符具体干了怎么呢?其实很轻松,就干了三件业务。

复制代码 代码如下:

var obj = {};
obj.__proto__ = Base.prototype;
Base.call(obj);

 

原型链

原型链:当从二个指标这里调取属性或艺术时,若是该对象自己不设有这么的性质或格局,就能够去本身关系的prototype对象这里找出,要是prototype未有,就会去prototype关联的长辈prototype这里寻觅,假诺再未有则再三再四搜寻Prototype.Prototype引用的靶子,依次类推,直到Prototype.….Prototype为undefined(Object的Prototype正是undefined)进而形成了所谓的“原型链”。

 

复制代码 代码如下:

<script type="text/javascript">
function Shape(){
this.name = "shape";
this.toString = function(){
return this.name;
}
}
function TwoShape(){
this.name = "2 shape";
}
function Triangle(side,height){
this.name = "Triangle";
this.side = side;
this.height = height;
this.getArea = function(){
return this.side*this.height/2;
}
}

 

TwoShape.prototype = new Shape();
Triangle.prototype = new TwoShape();
</script>

 

此地,用构造器Shape()新建了一个实体,然后用它去掩没该对象的原型。

复制代码 代码如下:

<script type="text/javascript">
function Shape(){
this.name = "shape";
this.toString = function(){
return this.name;
}
}
function TwoShape(){
this.name = "2 shape";
}
function Triangle(side,height){
this.name = "Triangle";
this.side = side;
this.height = height;
this.getArea = function(){
return this.side*this.height/2;
}
}

 

TwoShape.prototype = new Shape();
Triangle.prototype = new TwoShape();

TwoShape.prototype.constructor = TwoShape;
Triangle.prototype.constructor = Triangle;

var my = new Triangle(5,10);
my.getArea();
my.toString();//Triangle
my.constructor;//Triangle(side,height)
</script>

 

原型承继

原型承袭:在原型链的末端,就是Object构造函数prototype属性指向的丰裕原型对象。这一个原型对象是独具指标的先人,这些老祖宗完成了诸如toString等具备指标自然就该具有的点子。别的内置构造函数,如Function,Boolean,String,Date和RegExp等的prototype都以从这一个老祖宗承接下去的,但他们分别又定义了自家的性质和办法,进而他们的子孙就表现出个别宗族的那贰个特征。

ECMAScript中,实现持续的法子就是凭仗原型链达成的。

复制代码 代码如下:

<script type="text/javascript">
function Box(){ //被承袭的函数叫做超类型(父类,基类)
this.name = "Jack";
}

 

function Tree(){ //传承的函数叫做子类型(子类,派生类)
this.age = 300;
}
//通过原型链承继,赋值给子类型的原型属性
//new Box()会将box构造里的音信和原型里的信息都付出Tree
Tree.prototype = new 博克斯();//Tree承继了Box,通过原型,形成链条

var tree = new Tree();
alert(tree.name);//弹出 Jack
</script>

 

原型链的难题:原型链纵然很有力,能够用它来贯彻持续,但它也设有部分标题。当中最关键的标题来自蕴涵援用类型的值原型。包涵引用类型的原型属性会被全部实例共享;而这也多亏为啥要在构造函数中,实际不是在原型对象中定义属性的案由。在通过原型来贯彻持续时,原型实际上回形成另二个类型的实例。于是,原先的实例属性也就成为了原型的性质。

在开创子类型的实例时,不能够向超类型的构造函数中传递参数。实际上,应该便是未有宗意在不影响全体指标实例的状态下,给超类型的构造函数字传送递参数。再增长刚刚探究的由于原型中蕴涵援用类型值所拉动的标题,实施中比非常少会单独选用原型链。

再举个栗子:

 

复制代码 代码如下:

<script type="text/javascript">
function Person(name)
{
this.name = name;//设置对象属性
};

 

Person.prototype.company = "Microsoft";//设置原型的性格
Person.prototype.SayHello = function() //原型的主意
{
alert("Hello,I'm "+ this.name+ " of " + this.company);
};

var BillGates = new Person("BillGates");//创建person对象
比尔Gates.SayHello();//承袭了原型的内容,输出"Hello,I'm 比尔Gates of Microsoft"

var Jobs = new Person("Jobs");
Jobs.company = "Apple";//设置自身的company属性,掩瞒了原型的company属性
Jobs.SayHello = function()
{
alert("Hi,"+this.name + " like " + this.company);
};
Jobs.SayHello();//本人掩没的性质和方式,输出"Hi,Jobs like Apple"
BillGates.SayHello();//Jobs的覆盖未有影响原型,BillGates依然照旧输出
</script>

 

看下边三个原型链例子:

 

复制代码 代码如下:

<script type="text/javascript">
function Year(){
this.value = 21;
}
Year.prototype = {
method:function(){

 

}
};

function Hi(){

};
//设置Hi的prototype属性为Year的实例对象
Hi.prototype = new Year();
Hi.prototype.year = 'Hello World';

Hi.prototype.constructor = Hi;

var test = new Hi();//创造三个Hi的新实例

//原型链
test [Hi的实例]
Hi.prototype [Year的实例]
{year:'Hello World'}
Year.prototype
{method:……};
object.prototype
{toString:...};

</script>

 

从上边例子中,test对象从Hi.prototype和Year.prototype中持续下来;由此他能访问Year的原型方法method,同不常间她能访谈实例属性value

__ptoto__属性

__ptoto__质量(IE浏览器不帮衬)是实例指向原型对象的二个指针,它的成效正是指向构造函数的原型属性constructor,通过这两日特性,就可以访谈原型里的属性和措施了。

Javascript中的对象实例本质上是由一系列的属性组成的,在那一个属性中,有一个里边的不可以预知的异样性质——__proto__,该属性的值指向该对象实例的原型,贰个指标实例只持有叁个唯一的原型。

 

复制代码 代码如下:

<script type="text/javascript">
function Box(){ //大写,代表构造函数
Box.prototype.name = "trigkit4";//原型属性
Box.prototype.age = "21";
Box.prototype.run = function()//原型方法
{
return this.name + this.age + 'studying';
}
}

 

var box1 = new Box();
var box2 = new Box();
alert(box1.constructor);//构造属性,可以博得构造函数本人,
//功能是被原型指针定位,然后拿走构造函数自身
</script>

 

__proto__个性和prototype属性的区分

prototype是function对象中等专门的学业高校有的品质。
__proto__是常常对象的隐式属性,在new的时候,会针对prototype所指的对象;
__ptoto__实则是有个别实体对象的性质,而prototype则是属于构造函数的习性。__ptoto__只好在读书或调节和测量检验的条件下利用。

原型情势的施行流程

1.先查找构造函数实例里的性能或艺术,假使有,就当下回到。
2.万一构造函数的实例未有,就去它的原型对象里找,借使有,就立马回到

原型对象的

复制代码 代码如下:

<script type="text/javascript">
function Box(){ //大写,代表构造函数
Box.prototype.name = "trigkit4";//原型属性
Box.prototype.age = "21";
Box.prototype.run = function()//原型方法
{
return this.name + this.age + 'studying';
}
}

 

var box1 = new Box();
alert(box1.name);//trigkit4,原型里的值
box1.name = "Lee";
alert(box1.name);//Lee,就进原则

var box2 = new Box();
alert(box2.name);//trigkit4,原型的值,未有被box1修改
</script>

 

构造函数的

复制代码 代码如下:

<script type="text/javascript">
function Box(){
this.name = "Bill";
}

 

Box.prototype.name = "trigkit4";//原型属性
Box.prototype.age = "21";
Box.prototype.run = function()//原型方法
{
return this.name + this.age + 'studying';
}

var box1 = new Box();
alert(box1.name);//Bill,原型里的值
box1.name = "Lee";
alert(box1.name);//Lee,就进原则
</script>

 

综上,整理一下:

复制代码 代码如下:

<script type="text/javascript">
function Person(){};

 

Person.prototype.name = "trigkit4";
Person.prototype.say = function(){
alert("Hi");
}

var p1 = new Person();//prototype是p1和p2的原型对象
var p2 = new Person();//p2为实例化对象,其里面有叁个__proto__属性,指向Person的prototype

console.log(p1.prototype);//undefined,那特性情是贰个指标,访谈不到
console.log(Person.prototype);//Person
console.log(Person.prototype.constructor);//原型对象内部也许有二个指针(constructor属性)指向构造函数
console.log(p1.__proto__);//那个性情是壹个指针指向prototype原型对象
p1.say();//实例能够访谈到在原型对象上定义的品质和方法

</script>

 

工厂情势

复制代码 代码如下:

function createObject(name,age){
var obj = new Object();
obj.name = name;
obj.age = age;
return obj;
}

 

工厂方式消除了实例化对象多量再一次的标题,但还应该有二个难题,那正是根本不可能搞掌握他们到底是哪个目的的实例。
利用构造函数的艺术,既化解了再次实例化的标题,又缓和了对象识别的难点。

动用构造函数的法子和工厂形式的分化之处在于:

1.构造函数方法未有展现的创造对象(new Object());
2.直接将品质和格局赋值给this对象
3.没有return 语句

当使用了构造函数,何况new 构造函数(),那么就在后台实践了new Object();
函数体内的this代表了new Object()出来的对象

1.剖断属性是在构造函数的实例里,依然在原型里,能够采用`hasOwnProperty()`函数
2.字面量创造的不二等秘书诀选择constructor属性不会指向实例,而会指向Object,构造函数创制的格局则相反
怎么指向Object?因为Box.prototype = {};这种写法其实就是创建了贰个新对象。
而每成立贰个函数,就能同一时候创建它的prototype,那个目的也会活动获得constructor属性
3.只假设实例方法,差别的实例化,他们的法子地址是区别样的,是无与伦比的
4.假使是原型方法,那么他们的地方的分享的

那篇小说首要介绍了JavaScript中原型和原型链详解,本文疏解了个人变量和函数、静态变量和函数、实例变量和函...

  1. 面向对象具备类的定义,通过类能够成立率性八个一样的属性和艺术。

  2. ECMA-262把目的定义为:冬季属性的联谊,其属性包涵基本值、对象或函数。

  3. ECMAScript中有二种属性:数据属性,访谈器属性。

一、对象的概念

在ECMAScript-26第22中学,对象被定义为“冬天属性的联谊,其性质能够分包基本值,对象只怕函数”

也正是说,在JavaScript中,对象只是就是由局部列冬辰的key-value对构成。当中value能够是基本值,对象可能函数。

// 这里的person正是三个目标 var person = { name: '汤姆', age: 18, getName: function() {}, parent: {} }

1
2
3
4
5
6
7
// 这里的person就是一个对象
var person = {
    name: 'Tom',
    age: 18,
    getName: function() {},
    parent: {}
}

创设对象

我们得以经过new的办法创建多少个指标。

var obj = new Object();

1
var obj = new Object();

也足以通过对象字面量的花样创造贰个简易的对象。

var obj = {};

1
var obj = {};

当大家想要给大家制造的简要对象增添方法时,能够这么表示。

// 能够如此 var person = {}; person.name = "TOM"; person.getName = function() { return this.name; } // 也能够那样 var person = { name: "TOM", getName: function() { return this.name; } }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 可以这样
var person = {};
person.name = "TOM";
person.getName = function() {
    return this.name;
}
 
// 也可以这样
var person = {
    name: "TOM",
    getName: function() {
        return this.name;
    }
}

拜谒对象的习性和艺术

要是我们有贰个简单易行的目的如下:

var person = { name: 'TOM', age: '20', getName: function() { return this.name } }

1
2
3
4
5
6
7
var person = {
    name: 'TOM',
    age: '20',
    getName: function() {
        return this.name
    }
}

当我们想要访谈他的name属性时,能够用如下三种办法访谈。

person.name // 或者 person['name']

1
2
3
4
person.name
 
// 或者
person['name']

一旦大家想要访谈的属性名是三个变量时,平日会选择第二种办法。举例大家要同一时间做客person的name与age,可以如此写:

['name', 'age'].forEach(function(item) { console.log(person[item]); })

1
2
3
['name', 'age'].forEach(function(item) {
    console.log(person[item]);
})

这种措施势须求尊敬,记住它曾经在大家管理目眩神摇数据的时候会有相当的大的帮带。

1. Object构造函数

var person = new Object();
person.name = "Brittany";
person.age = 23;
person.job = "web front-end engineer";
person.sayName = function() {
    console.log(this.name);
};
person.sayName();   //Brittany

复制代码 代码如下:

有关小说

连锁寻找:

今日看啥

搜寻才干库

归来首页

  • IOS8气象应用能够来得细节数量本领
  • CADMini看图怎么着查看设备清单
  • SamsungMate7怎么样展开按电源键截止通话
  • 微型Computer回收站不可能调解体量的轻重缓急如何是好?
  • 新三板是怎么看头
  • 什么在win7运动版计算机中剔除U盘使用历史记录

有关频道: HTML/CSS  HTML5  Javascript  jQuery  AJax教程  前面一个代码  正则表明式  Flex教程  WEB前端教程  

4. 数额属性: configurable, enumerable, writable, value

二、工厂格局

选拔方面包车型大巴点子成立对象非常粗略,但是在众多时候并不可能满意我们的供给。就以person对象为例。假若大家在实际上支付中,不仅要求几个名字称为TOM的person对象,同期还供给另外四个名叫Jake的person对象,就算她们有多数相似之处,但是我们只可以再次写五次。

var perTom = { name: 'TOM', age: 20, getName: function() { return this.name } }; var perJake = { name: 'Jake', age: 22, getName: function() { return this.name } }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var perTom = {
    name: 'TOM',
    age: 20,
    getName: function() {
        return this.name
    }
};
 
var perJake = {
    name: 'Jake',
    age: 22,
    getName: function() {
        return this.name
    }
}

很醒目那并不是合情的主意,当相似对象太多时,我们都会崩溃掉。

我们能够运用工厂形式的格局缓和那个难题。从名称想到所包括的意义,工厂形式正是大家提供三个模型,然后经过那个模型复制出大家必要的靶子。我们供给有个别个,就复制多少个。

var createPerson = function(name, age) { // 声可瑞康在那之中路对象,该目的便是工厂方式的模型 var o = new Object(); // 依次增加大家供给的个性与措施 o.name = name; o.age = age; o.getName = function() { return this.name; } return o; } // 成立四个实例 var perTom= createPerson('TOM', 20); var PerJake = createPerson('Jake', 22);

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
var createPerson = function(name, age) {
 
    // 声明一个中间对象,该对象就是工厂模式的模子
    var o = new Object();
 
    // 依次添加我们需要的属性与方法
    o.name = name;
    o.age = age;
    o.getName = function() {
        return this.name;
    }
 
    return o;
}
 
// 创建两个实例
var perTom = createPerson('TOM', 20);
var PerJake = createPerson('Jake', 22);

深信不疑上边的代码并简单掌握,也不用把工厂方式看得太过巨大上。很料定,工厂方式帮助大家消除了再也代码上的难为,让大家得以写少之又少的代码,就能够创造相当多少个person对象。然而此地还应该有八个艰难,供给大家注意。

首先个麻烦正是这么管理,大家尚无主意鉴定识别对象实例的档案的次序。使用instanceof能够识别对象的种类,如下例子:

var obj = {}; var foo = function() {} console.log(obj instanceof Object); // true console.log(foo instanceof Function); // true

1
2
3
4
5
var obj = {};
var foo = function() {}
 
console.log(obj instanceof Object);  // true
console.log(foo instanceof Function); // true

故此在工厂情势的根底上,我们供给利用构造函数的主意来消除这几个麻烦。

2. 对象字面量形式

var person = {
    name: "Brittany",
    age: 23,
    job: "web front-end engineer",
    sayName: function() {
        console.log(this.name);
    }
};
person.sayName();

即便Object构造函数或对象字面量都能够用来创建单个对象,但这一个措施有个明明的短处:使用同一个接口制造非常多指标,会生出大批量的重复代码。为解决这些主题材料,可以动用工厂格局的一种变体。

A.prototype = new B();

帮顾客量

  1. 修改属性默许的性状: Object.defineProperty();

三、构造函数

在JavaScript中,new关键字能够让多个函数变得极度。通过下边包车型客车事例,我们来一探new关键字的神奇之处。

function demo() { console.log(this); } demo(); // window new demo(); // demo

1
2
3
4
5
6
function demo() {
    console.log(this);
}
 
demo();  // window
new demo();  // demo

为了能够直观的感受他们不等,建议大家入手实行观望一下。很醒目,使用new之后,函数内部发生了有的改造,让this指向改造。那么new关键字到底做了怎么样业务呢。嗯,其实作者事先在小说里用文字大约表明了刹那间new到底干了什么样,可是某个同桌好奇心很足,总希望用代码达成一下,小编就差十分少以作者的知晓来发挥一下吗。

// 先一本正经的始建一个构造函数,其实该函数与日常函数并无差别 var Person = function(name, age) { this.name = name; this.age = age; this.getName = function() { return this.name; } } // 将构造函数以参数情势传播 function New(func) { // 声爱他美(Aptamil)个个中对象,该对象为结尾回到的实例 var res = {}; if (func.prototype !== null) { // 将实例的原型指向构造函数的原型 res.__proto__ = func.prototype; } // ret为构造函数实践的结果,这里透过apply,将构造函数内部的this指向修改为指向res,即为实例对象 var ret = func.apply(res, Array.prototype.slice.call(arguments, 1)); // 当大家在构造函数中鲜明钦赐了回去对象时,那么new的推行结果就是该再次来到对象 if ((typeof ret === "object" || typeof ret === "function") && ret !== null) { return ret; } // 若无明了钦点重临对象,则暗许重临res,这一个res便是实例对象 return res; } // 通过new证明创造实例,这里的p1,实际摄取的难为new中回到的res var p1 = New(Person, 'tom', 20); console.log(p1.getName()); // 当然,这里也足以决断出实例的项目了 console.log(p1 instanceof Person); // true

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
// 先一本正经的创建一个构造函数,其实该函数与普通函数并无区别
var Person = function(name, age) {
    this.name = name;
    this.age = age;
    this.getName = function() {
        return this.name;
    }
}
 
// 将构造函数以参数形式传入
function New(func) {
 
    // 声明一个中间对象,该对象为最终返回的实例
    var res = {};
    if (func.prototype !== null) {
 
        // 将实例的原型指向构造函数的原型
        res.__proto__ = func.prototype;
    }
 
    // ret为构造函数执行的结果,这里通过apply,将构造函数内部的this指向修改为指向res,即为实例对象
    var ret = func.apply(res, Array.prototype.slice.call(arguments, 1));
 
    // 当我们在构造函数中明确指定了返回对象时,那么new的执行结果就是该返回对象
    if ((typeof ret === "object" || typeof ret === "function") && ret !== null) {
        return ret;
    }
 
    // 如果没有明确指定返回对象,则默认返回res,这个res就是实例对象
    return res;
}
 
// 通过new声明创建实例,这里的p1,实际接收的正是new中返回的res
var p1 = New(Person, 'tom', 20);
console.log(p1.getName());
 
// 当然,这里也可以判断出实例的类型了
console.log(p1 instanceof Person); // true

JavaScript内部再经过另外的有些非正规管理,将var p1 = New(Person, 'tom', 20); 等效于var p1 = new Person('tom', 20);。正是我们认知的new关键字了。具体怎么管理的,小编也不理解,别刨根问底了,一向回答下去太难 – -!

规矩讲,你只怕很难在此外地点来看有这么扎眼的告知你new关键字到底对构造函数干了怎么着的稿子了。明白了这段代码,你对JavaScript的理解又比别人深远了一分,所以,作古正经下流至极求个赞可好?

理所必然,非常多有恋人由于对于日前几篇小说的知识精晓非常不够成功,会对new的兑现表示非凡纳闷。可是老实讲,尽管你读了本人的眼前几篇文章,一定会对此处new的落到实处有似曾相识的认为。并且本人这里已经努力做了详尽的疏解,剩下的只好靠你谐和了。

可是假设你花点时间,精晓了他的准则,那么麻烦了广大人的构造函数中this到底指向何人就变得特别轻易了。

之所以,为了能够判明实例与对象的关联,大家就应用构造函数来化解。

var Person = function(name, age) { this.name = name; this.age = age; this.getName = function() { return this.name; } } var p1 = new Person('Ness', 20); console.log(p1.getName()); // Ness console.log(p1 instanceof Person); // true

1
2
3
4
5
6
7
8
9
10
11
12
var Person = function(name, age) {
    this.name = name;
    this.age = age;
    this.getName = function() {
        return this.name;
    }
}
 
var p1 = new Person('Ness', 20);
console.log(p1.getName());  // Ness
 
console.log(p1 instanceof Person); // true

有关构造函数,假如你近来不可以知道通晓new的切实可行落到实处,就先记住上边这多少个结论吧。

  • 与平日函数比较,构造函数并不曾别的极度的地点,首字母大写只是咱们约定的小规定,用于区分普通函数;
  • new关键字让构造函数具备了与常见函数分裂的多多风味,而new的进程中,实行了之类进程:
    1. 宣示贰当中级对象;
    2. 将该中间对象的原型指向构造函数的原型;
    3. 将构造函数的this,指向该中间对象;
    4. 再次来到该中间对象,即重回实例对象。

3. 厂子方式 

function createPerson(name, age, job) {
    var o = new Object();
    o.name = name;
    o.age = age;
    o.job = job;
    o.sayName = function() {
        console.log(this.name);
    };
    return o;
}

var person1 = createPerson("Brittany", 23, "Software Engineer");
var person2 = createPerson("Sam", 26, "Software Engineer");
console.log(typeof person1);   //Object

厂子方式固然缓和了创办多少个日常对象的标题,但却从不缓慢解决对象识其余难点(即什么精通一个对象的类型)。如代码中不得不检查实验出person1为Object类型。随着JavaScript的前进,又二个新形式出现了。

接头prototype不应把它和三回九转混淆。A的prototype为B的二个实例,能够精通A将B中的方法和总体性全体仿制了一回。A能使用B的方法和性质。这里重申的是仿造并非继续。能够出现这种景况:A的prototype是B的实例,同一时候B的prototype也是A的实例。

6. Object.defineProperty(person, name, {

四、原型

固然如此构造函数解决了判定实例类型的难点,然而,谈起底,依旧二个对象的复制进程。跟工厂情势颇具相似之处。也正是说,当大家注明了九17个person对象,那么就有玖拾玖个getName方法被重新生成。

此地的每一个getName方法完毕的成效实在是大同小异的,不过出于各自属于差别的实例,就只能直接不停的为getName分配空间。那便是工厂格局存在的第4个麻烦。

芸芸众生那是不客观的。大家盼望的是,既然都以兑现同一个功力,那么能还是无法就让各种实例对象都采访同贰个措施?

本来能,那正是原型对象要帮大家缓慢解决的标题了。

作者们创造的每三个函数,都得以有二个prototype属性,该属性指向三个目的。这一个目的,就是大家那边说的原型。

当咱们在创制对象时,能够依赖本人的需要,选用性的将一部分属性和方法通过prototype属性,挂载在原型对象上。而每一个new出来的实例,皆有三个__proto__脾气,该属性指向构造函数的原型对象,通过那一个天性,让实例对象也能够访谈原型对象上的措施。因而,当有着的实例都能够通过__proto__访问到原型对象时,原型对象的法子与品质就成为了共有方法与个性。

咱俩由此一个粗略的例证与图示,来打听构造函数,实例与原型三者之间的关联。

鉴于每一种函数都能够是构造函数,种种对象都能够是原型对象,因而一旦在领略原型之初就想的太多太复杂的话,反而会阻拦你的敞亮,这里我们要学会先简化它们。就独有的分析那三者的关系。

// 注明构造函数 function Person(name, age) { this.name = name; this.age = age; } // 通过prototye属性,将艺术挂载到原型对象上 Person.prototype.getName = function() { return this.name; } var p1 = new Person('tim', 10); var p2 = new Person('jak', 22); console.log(p1.getName === p2.getName); // true

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 声明构造函数
function Person(name, age) {
    this.name = name;
    this.age = age;
}
 
// 通过prototye属性,将方法挂载到原型对象上
Person.prototype.getName = function() {
    return this.name;
}
 
var p1 = new Person('tim', 10);
var p2 = new Person('jak', 22);
console.log(p1.getName === p2.getName); // true

图片 6

图示

由此图示我们能够见到,构造函数的prototype与具备实例对象的__proto__都针对原型对象。而原型对象的constructor指向构造函数。

除了那么些之外,还可以从图中看出,实例对象实际对近来大家所说的高级中学级对象的复制,而中等对象中的属性与措施都在构造函数中丰裕。于是依照构造函数与原型的特征,大家就能够就要构造函数中,通过this注解的质量与方法称为私有变量与方法,它们被日前被某叁个实例对象所独有。而经过原型注脚的天性与措施,大家能够称呼共有属性与艺术,它们能够被有着的实例对象访谈。

当大家访谈实例对象中的属性只怕措施时,会先行访谈实例对象自己的习性和章程。

function Person(name, age) { this.name = name; this.age = age; this.getName = function() { console.log('this is constructor.'); } } Person.prototype.getName = function() { return this.name; } var p1 = new Person('tim', 10); p1.getName(); // this is constructor.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function Person(name, age) {
    this.name = name;
    this.age = age;
    this.getName = function() {
        console.log('this is constructor.');
    }
}
 
Person.prototype.getName = function() {
    return this.name;
}
 
var p1 = new Person('tim', 10);
 
p1.getName(); // this is constructor.

在这一个例子中,大家同不时候在原型与构造函数中都声称了一个getName函数,运转代码的结果表示原型中的访谈并从未被访谈。

大家还是能通过in来判别,八个目的是不是富有某贰个天性/方法,无论是该属性/方法存在与实例对象依然原型对象。

function Person(name, age) { this.name = name; this.age = age; } Person.prototype.getName = function() { return this.name; } var p1 = new Person('tim', 10); console.log('name' in p1); // true

1
2
3
4
5
6
7
8
9
10
11
12
function Person(name, age) {
    this.name = name;
    this.age = age;
}
 
Person.prototype.getName = function() {
    return this.name;
}
 
var p1 = new Person('tim', 10);
 
console.log('name' in p1); // true

in的这种特征最常用的面貌之一,正是决断当前页面是或不是在运动端张开。

isMobile = 'ontouchstart' in document; // 很四人爱怜得舍不得放手用浏览器UA的法子来推断,但实际不是很好的办法

1
2
3
isMobile = 'ontouchstart' in document;
 
// 很多人喜欢用浏览器UA的方式来判断,但并不是很好的方式

更简便的原型写法

基于前边例子的写法,假若大家要在原型上加多更加多的艺术,能够这么写:

function Person() {} Person.prototype.getName = function() {} Person.prototype.getAge = function() {} Person.prototype.sayHello = function() {} ... ...

1
2
3
4
5
6
function Person() {}
 
Person.prototype.getName = function() {}
Person.prototype.getAge = function() {}
Person.prototype.sayHello = function() {}
... ...

除此之外,小编还是能选拔更为简易的写法。

function Person() {} Person.prototype = { constructor: Person, getName: function() {}, getAge: function() {}, sayHello: function() {} }

1
2
3
4
5
6
7
8
function Person() {}
 
Person.prototype = {
    constructor: Person,
    getName: function() {},
    getAge: function() {},
    sayHello: function() {}
}

这种字面量的写法看上去差非常的少比非常多,然而有二个急需特别注意的地点。Person.prototype = {}实质上是再度创造了一个{}指标并赋值给Person.prototype,这里的{}并不是开始时代的那二个原型对象。因而它里面并不分包constructor质量。为了确认保证科学,大家不能够不在新成立的{}指标中展现的设置constructor的指向。即上边的constructor: Person

4. 构造函数形式

function Person(name, age, job) {
    this.name = name;
    this.age = age;
    this.job = job;
    this.sayName = function() {
        console.log(this.name);
    }    
}
var person1 = new Person("Brittany", 23, "Web front-end engineer");
var person2 = new Person("Closure", 26, "Manager");
person1.sayName();
person2.sayName();
console.log(person1.sayName == person2.sayName);   //false

使用构造函数的显要难题:各样方法都要在每一个实例上再度成立一次。如代码中所示,person1的sayName和person2的sayName不等于。能够将函数定义转移到构造函数外界来化解。

function Person(name, age, job) {
    this.name = name;
    this.age = age;
    this.job = job;
    this.sayName = sayName;
}
function sayName() {
    console.log(this.name);
}

sayName函数的概念转移到了构造函数外界。而在构造函数内部,大家将sayName属性设置成等于全局的sayName函数。那样一来,由于sayName包涵的是壹个针对函数的指针,由此person1和person2对象就分享了在全局成效域中定义的同二个sayName()函数。这真的消除了五个函数做同样件事的主题素材,不过新主题材料又来了:在大局成效域中定义的函数实际上只可以被有个别对象调用,那让全局功能域有一点老婆当军。而更让令人敬敏不谢承受的是:借使必要定义相当多艺术,那就要定义比非常多个全局函数,于是这些自定义的援用类型就无封装性可言。这一个主题素材可经过应用原型情势来消除。

后续看上面的分析:

  writable: false,

四、原型链

原型对象实际也是普普通通的靶子。大概具有的对象都只怕是原型对象,也大概是实例对象,何况还足以同不常候是原型对象与实例对象。那样的二个目的,就是结合原型链的一个节点。因而掌握了原型,那么原型链实际不是三个多么繁琐的概念。

我们知道全部的函数都有一个堪当toString的议程。那么那个艺术到底是在哪个地方的啊?

先随机注明一(Aptamil)个函数:

function foo() {}

1
function foo() {}

那么大家能够用如下的图来代表那一个函数的原型链。

图片 7

原型链

里头foo是Function对象的实例。而Function的原型对象同不时候又是Object的实例。那样就重组了一条原型链。原型链的访问,其实跟功用域链有不小的相似之处,他们都以叁次单向的找出进程。由此实例对象能够通过原型链,访谈到地处原型链上对象的享有属性与方式。那也是foo最后能够访谈到地处Object原型对象上的toString方法的原由。

基于原型链的特点,大家能够很自在的落到实处继承

5. 原型方式

民用变量和函数

  value: 'xhk'
  })

五、继承

小编们平常结合构造函数与原型来创立叁个指标。因为构造函数与原型的例外风味,分别解决了笔者们分化的干扰。由此当大家想要完结持续时,就务须得依照构造函数与原型的两样而选拔两样的计划。

我们声Bellamy(Bellamy)个Person对象,该指标将用作父级,而子级cPerson将在继续Person的享有属性与措施。

function Person(name, age) { this.name = name; this.age = age; } Person.prototype.getName = function() { return this.name; }

1
2
3
4
5
6
7
8
function Person(name, age) {
    this.name = name;
    this.age = age;
}
 
Person.prototype.getName = function() {
    return this.name;
}

率先大家来看构造函数的接轨。在上头我们早就通晓了构造函数的本来面目,它事实上是在new内部完成的三个复制进度。而大家在后续时想要的,正是想父级构造函数中的操作在子级的构造函数中复发一遍就能够。大家能够透过call方法来完毕指标。

// 构造函数的接轨 function cPerson(name, age, job) { Person.call(this, name, age); this.job = job; }

1
2
3
4
5
// 构造函数的继承
function cPerson(name, age, job) {
    Person.call(this, name, age);
    this.job = job;
}

而原型的接续,则只须要将子级的原型对象设置为父级的三个实例,加入到原型链中就能够。

// 承袭原型 cPerson.prototype = new Person(name, age); // 加多更多措施 cPerson.prototype.getLive = function() {}

1
2
3
4
5
// 继承原型
cPerson.prototype = new Person(name, age);
 
// 添加更多方法
cPerson.prototype.getLive = function() {}

图片 8

原型链

自然关于一而再还大概有越来越好的法子,这里就不做深入介绍了,以往有空子再详尽解读呢。

1)对象创设 

function Person() {}
Person.prototype.name = "Brittany";
Person.prototype.age = 23;
Person.prototype.job = "Web front-end engineer";
Person.prototype.getName = function() {
    console.log(this.name);
};
var p1 = new Person();
var p2 = new Person();

console.log(p1.name);                    //Brittany
console.log(p2.name);                    //Brittany
console.log(p1.getName == p2.getName);   //true

实例中开创的属性会覆盖原型中的同名属性,不可能改改原型中的属性。

p1.name = "Susan";
console.log(p1.name);                    //Susan

hasOwnProperty()检查评定贰本性格是还是不是留存于实例中。

console.log(p2.hasOwnProperty("name"));  //false
p2.name = "koko";
console.log(p2.hasOwnProperty("name"));  //true
delete p2.name;
console.log(p2.hasOwnProperty("name"));  //false

isPropertyOf()

console.log(Person.prototype.isPrototypeOf(p1));   //true
console.log(Person.prototype.isPrototypeOf(p2));   //true

getPropertyOf()

console.log(Object.getPrototypeOf(p1) == Person.prototype);  //true
console.log(Object.getPrototypeOf(p1));                      //Person

在函数内部定义的变量和函数,要是不对外提供接口,外界是无法访谈到的,也正是该函数的个人的变量和函数。

 person.name  // 'xhk'

六、总结

关于面向对象的基础知识大约便是那几个了。作者从最简便易行的开创二个指标开首,解释了怎么大家供给构造函数与原型,掌握了那个中的细节,有协理大家在实际开销中灵活的团体自个儿的靶子。因为大家并非有所的风貌都会利用构造函数或许原型来创造对象,也许我们供给的目的并不会注解八个实例,大概不用区分对象的体系,那么大家就能够挑选更简约的法子。

我们还索要关心构造函数与原型的个别特色,有利于大家在创制对象时准确的论断大家的属性与艺术到底是放在构造函数中大概放在原型中。若无领会了解,那会给我们在事实上支付中变成非常的大的麻烦。

末段接下去的几篇小说,作者会挑几个面向对象的例证,继续帮忙大家精通面向对象的其实使用。

2 赞 4 收藏 1 评论

图片 9

2)原型与in操作符

in单独行使时,通过对象访谈到特定属性时回来true,无论该属性存在于实例中如故原型中。hasOwnProperty(),通过对象访谈到一定属性时回来true,且该属性存在于实例中。 

var p3 = new Person();
console.log("name" in p3);                //true
console.log(p3.hasOwnProperty("name"));   //false
p3.name = "insist";
console.log(p3.hasOwnProperty("name"));   //true

鲜明属性到底是存在于对象中,依然存在于原型中。如下函数hasPrototypePropery()重临true表示该属性存在于原型中,实际不是存在于实例中。

function hasPrototypeProperty(object, name) {
    return !hasOwnProperty("name") && (name in object);
}

for..in循环,全体通过对象能够访谈的,可枚举的(enumerated)属性,既包蕴存在于实例中的属性,也满含存在于原型中的属性。

for(var prop in p1) {
    console.log(prop);                    //name age job sayName
}

Object.keys(),ECMAScript5的方式,取得对象上全数可枚举的本性,接收八个对象作为参数,再次来到值是二个富含全数可枚举属性的字符串数组。注意:Person.prototype也是指标。

var keys = Object.keys(Person.prototype);
console.log(keys);             //["name age job sayName"]
var p1 = new Person(); 
console.log(Object.keys(p1));  //[]
p1.name = "get";
console.log(Object.keys(p1));  //["name"]

Object.getOwnPropertyNames(),获得全部实例属性,无论它是否可枚举。

var keys = Object.getOwnPropertyNames(Person.prototype);
console.log(keys);     //["constructor", "name", "age", "job", "getName"] 
var keys_p1 = Object.getOwnPropertyNames(p1);
console.log(keys_p1);  //[]

复制代码 代码如下:

    person.name = 'coco';

3)更轻巧的原型语法

function Person() {}
Person.prototype = {
    name: "Brittany",
    age: 23,
    job: "Web front-end engineer",
    getName: function() {
        return this.name;
    }
};
var friend = new Person();
console.log(friend instanceof Person);      //true
console.log(friend instanceof Object);      //true
console.log(friend.constructor == Person);  //false
console.log(friend.constructor == Object);  //false

在上头的代码中,将Person.prototype设置为等于三个对象字面量方式成立的新指标,最后结出同样。但有二个见仁见智:constructor属性不再指向Person了。每创造一个函数,就能够同期成立它的prototype对象,那么些指标也会自动获得constructor属性。而小编辈在那边运用的语法,本质上完全重写了暗中同意的prototype对象,由此constructor属性也就改为了新目的的constructor属性(指向Object构造函数),不再指向Person函数。此时尽管instanceof操作符还可以够重回正确的结果,但经过constructor已经江郎才尽鲜明指标的体系了。

因而如下格局,将constructor手动设置为适龄的值。

Person.prototype = {
    constructor: Person,
    name: "Brittany",
    age: 23,
    job: "Web front-end engineer",
    getName: function() {
        console.log(this.name);
    }
};

<script type="text/javascript">
    function Box(){
        var color = "blue";//私有变量
        var fn = function() //私有函数
        {

    person.name   // 'xhk'

4)原型的动态性

在原型中查找值的经过是二次寻找,由此大家对原型对象所做的别的修改都能够致时从实例上反映出去——固然是先创建了实例后修改原型也照样如此。

var friend = new Person();
Person.prototype.sayHi = function() {
    console.log("hi");
};
friend.sayHi();

尽管能够随即为原型增多属性和办法,何况修改能够即时在颇有目的实例中展示出来,但如若是重写整个原型对象,情形就区别了。

function Person() {}
var friend = new Person();
Person.prototype = {
    constructor: Person,
    name: "Brittany",
    age: 23,
    job: "Web front-end engineer",
    getName: function() {
        console.log(this.name);
    }
};
friend.getName();                  //error

只要创制实例放在重写原型对象之后,则不会报错。

        }
    }
</script>

7. 访谈器属性不含有数据值,它们含有一群getter, setter函数(不过她们都不是必得的)。在读取访谈器属性的时候,会调用gettter函数,这一个函数肩负重回有效的值;   在写入访谈器属性的时候,调用setter函数,那一个函数肩负调控哪些管理数据。

5)原生对象的原型

抱有原生援用类型(Object、Array、String)都在其构造函数的原型上定义了艺术,如:Array.prototype.sort()、String.prototype.subString(), 通过原生对象的原型能够取得具备暗中认可方法的引用,并得以定义新措施。

console.log(typeof Array.prototype.sort);        //function
console.log(typeof String.prototype.substring);  //function

String.prototype.startsWith = function(text) {
    return this.indexOf(text) == 0;
};
var msg = "Hello World";
console.log(msg.startsWith("Hello"));           //true

这么在函数对象Box外界不也许访谈变量color和fn,他们就改成私有的了:

  1. 做客器属性:configurable,enumerable, get, set。访谈器属性不能够直接定义,须求使用Object.defineProperty();

6)原型对象的主题材料

症结一:省略了为构造函数字传送递开头化参数这一环节,结果有所实例在暗中认可意况下将得到一致的属性值。

缺点二:原型中有所属性被广大实例分享,这种分享对于函数非常相符。对于蕴涵基本值属性倒也说得过去,因为经过在实例上增多四个同名属性,能够隐蔽原型中对应的性格。但对此饱含援引类型值得属性来讲,难题相比较非凡。

function Person() { }
Person.prototype = {
    constructor: Person,
    name: "Brittany",
    friends: ["pink", "judy", "sam"],
    age: 23,
    job: "Web front-end engineer",
    getName: function() {
        console.log(this.name);
    }
};
var person1 = new Person();
var person2 = new Person();
person1.friends.push("leo");
console.log(person1.friends);           //["pink", "judy", "sam", "leo"]
console.log(person2.friends);           //["pink", "judy", "sam", "leo"]
console.log(Person.prototype.friends);  //["pink", "judy", "sam", "leo"]
person1.age = 35;
console.log(person1.age);           //35
console.log(person2.age);           //23
console.log(Person.prototype.age);  //23

person1的friends属性修改影响了person2的friends,可是person1的age属性修改并未影响person2的age属性。

缘由在于:friends数组存在于Person.prototype中而非person第11中学,由此修改也会透过person2.friends(与person1.friends指向同二个数组)反映出去。而age属性在person第11中学也存在一份,修改的age属性只是修改person第11中学的,并不能够改改Person.prototype中的age属性。

复制代码 代码如下:

9.  定义七个属性Object.defineProperties();

6. 结合使用构造函数情势和原型情势

构造函数格局用于定义实例属性,而原型格局用于定义方法和分享的性质。那样,每一种实例都会有谈得来的一份实例属性的别本,但又相同的时候分享着对章程的援用。

function Person(name, age, job) {
    this.name = name;
    this.age = age;
    this.job = job;
    this.friends = ["aa", "bb", "cc"];
}
Person.prototype = {
    constructor: Person,
    sayName: function() {
        console.log(this.name);
    }
};
var person1 = new Person("Brittany", 23, "Web front-end Engineer");
person1.friends.push("dd");     //["aa", "bb", "cc", "dd"]
console.log(person1.friends);
var person2 = new Person("Sam", 26, "Web front-end Engineer");
console.log(person2.friends);   //["aa", "bb", "cc"]
console.log(person1.friends == person2.friends);  //false
console.log(person1.sayName == person2.sayName);  //true

 

 

时间:2014-10-21

地点:合肥

援引:《JavaScript高级程序设计》 

var obj = new Box();
    alert(obj.color);//弹出 undefined
    alert(obj.fn);//同上

  1. 读取属性的天性: Object.getOwnPropertyDescriptor(); 获取给定属性的描述符,参数一,属性所在的靶子,参数二,要读取其陈诉符的属性名称。再次回到值是三个对象,假若是访谈器属性,重回configurable,enumerable, get, set;假如是数量属性,则赶回configurable,enumerable,writable, value.

静态变量和函数

11.  创制对象

当定义多少个函数后透过点号 “.”为其丰硕的性质和函数,通过对象自己还能访问获得,可是其实例却访问不到,那样的变量和函数分别被称呼静态变量和静态函数。

  使用同一个接口创建相当多对象,会发出巨量的重新代码。

复制代码 代码如下:

  1)工厂格局:用函数来封装以一定接口创制对象的底细,可以创设多个日常的对象。未有化解对象识别难题(即怎么样领会一个目的的种类)。

<script type="text/javascript">
    function Obj(){};

    function ceratePerson (name, age, gender) {
      var o = {};

    Obj.num = 72;//静态变量
    Obj.fn = function()  //静态函数
    {

      o.name = name;
      o.age = age;
      o.gender = gender;
      o.sayName = function() {
        console.log(this.name);
      }
    }

    } 

    var xhk = createPerson('xhk', 36, '男');

    alert(Obj.num);//72
    alert(typeof Obj.fn)//function

    xhk // {name: "xhk", age: 36, gender: "男", sayName: ƒ}

    var t = new Obj();
    alert(t.name);//undefined
    alert(typeof t.fn);//undefined
</script>

    xhk.sayName()  // xhk

实例变量和函数

    2)构造函数情势,创立自定义的构造函数,进而定义自定义对象类型的天性和方法。

在面向对象编程中除了某些库函数大家依旧期待在指标定义的时候还要定义一些品质和方法,实例化后可以访问,js也能完毕这样

      function Person(name, age, gender) {
        this.name = name;
        this.age = age;
        this.gender = gender;
        this.sayName = function() {
          console.log(name);
        }
      }

复制代码 代码如下:

      var p1 = new Person('xhk', 36, '男');  // Person {name: "xhk", age: 36, gender: "男", sayName: ƒ}

<script type="text/javascript">
          function Box(){
                this.a=[]; //实例变量
                this.fn=function(){ //实例方法

      构造函数形式和工厂形式的分别:  

                }
            }

      a. 未有显得的成立对象;

            console.log(typeof Box.a); //undefined
            console.log(typeof Box.fn); //undefined

      b. 直接将性能和艺术赋给了this对象;

            var box=new Box();
            console.log(typeof box.a); //object
            console.log(typeof box.fn); //function
</script>

      c. 没有return语句;

为实例变量和办法增多新的方法和属性

      要创造Person的新势力,必需利用new操作符,以这种办法调用构造函数实际上会经历一下多个步骤:

复制代码 代码如下:

      a. 创立二个新指标;

<script type="text/javascript">
function Box(){
                this.a=[]; //实例变量
                this.fn=function(){ //实例方法

      b. 将构造函数的效果与利益域赋给新对象(由此this指向了那个新目标);

                }
            }

      c. 实行构造函数中的代码(为那个新指标增多属性);

            var box1=new Box();
            box1.a.push(1);
            box1.fn={};
            console.log(box1.a); //[1]
            console.log(typeof box1.fn); //object

      d. 重临新指标;

本文由必威发布于必威-前端,转载请注明出处:A能使用B的方法和属性, 在写入访问器属性的时

相关阅读