JavaScript原型和原型链

 

 

    本文和大家分享的主要是javascript中原型和原型链相关内容,一起来看看吧,希望对大家学习javascript有所帮助。

  一切都是对象

  “一切都是对象这句话的重点在于如何去理解对象这个概念。

  概念

  JavaScript 中,万物皆对象!但对象也是有区别的。分为 普通对象  函数对象 Object Function 是 JS 自带的函数对象。

  当然,也不是所有的都是对象,值类型就不是对象。

  function show(x) {

  console.log(typeof x);    // undefined

  console.log(typeof 10);   // number

  console.log(typeof 'abc'); // string

  console.log(typeof true);  // boolean

  console.log(typeof function () {});  //function

  console.log(typeof [1, 'a', true]);  //object

  console.log(typeof { a: 10, b: 20 });  //object

  console.log(typeof null);  //object

  console.log(typeof new Number(10));  //object

  }

  show();

  以上代码列出了typeof输出的集中类型标识,其中上面的四种(undefined, number, string, boolean)属于简单的 值类型 ,不是对象。剩下的几种情况——函数、数组、对象、nullnew Number(10)都是对象。他们都是引用类型 

  对象——若干属性的集合

  概念

  数组是对象,函数是对象,对象还是对象。

  对象里面的一切都是属性,只有属性,没有方法

  那么这样方法如何表示呢?——方法也是一种属性。因为它的属性表示为键值对的形式。

  而且,javascript中的对象可以任意的扩展属性,没有class的约束。这个大家应该都知道,就不再强调了。

  先说个最常见的例子:

  var obj = {

  a: 10,

  b: function(x) {

  alert(this.a + x)

  },

  c: {

  name: "yzh",

  age: 21

  }

  }

  以上代码中,obj是一个自定义的对象,其中abc就是它的属性,而且在c的属性值还是一个对象,它又有nameyear两个属性。

  这个可能比较好理解,那么函数和数组也可以这样定义属性吗?——当然不行,但是它可以用另一种形式,总之函数/数组之流,只要是对象,它就是属性的集合。

  var fn = function () {

  alert(100);

  };

  fn.a = 10;

  fn.b = function () {

  alert(123);

  };

  fn.c = {

  name: "yzh",

  age: 21

  };

  上段代码中,函数就作为对象被赋值了abc三个属性——很明显,这就是属性的集合。

  (引用类型)都是对象,对象是属性的集合。最需要了解的就是对象的概念。

  创建对象

  前言

  这块在《JS高级程序设计》也算是大章节下的一块大内容,我只把一些重要的概念写出来让大家理解,具体的深入要自己去看书中的讲解。

  函数和对象的关系

  对象都是通过函数创建的

  function Fn() {

  this.name = 'yzh';

  this.year = 1996;

  }

  var fn1 = new Fn();

  有人可能会举出如下反例

  var obj = { a: 10, b: 20 };var arr = [5, 'x', true];

  这种做法属于使用快捷方式,在编程语言中,一般叫做语法糖

  其实以上代码的本质是:

  //var obj = { a: 10, b: 20 };//var arr = [5, 'x', true];

  var obj = new Object();

  obj.a = 10;

  obj.b = 20;

  var arr = new Array();

  arr[0] = 5;

  arr[1] = 'x';

  arr[2] = true;

  而其中的 Object 和 Array 都是函数:

  console.log(typeof (Object));  // functionconsole.log(typeof (Array));  // function

  总结:对象都是通过函数来创建的

  prototype

  函数也是一种对象。他也是属性的集合,你也可以对函数进行自定义属性

  每创建一个函数,就会同时创建函数的prototype对象。

  这个prototype的属性值是一个对象(属性的集合,再次强调!),默认的只有一个叫做constructor的属性,指向这个函数本身。

  function Fn() { }

  Fn.prototype.name = '王福朋';

  Fn.prototype.getYear = function () {

  return 1988;

  };

  var fn = new Fn();

  console.log(fn.name);

  console.log(fn.getYear());

  Fn是一个函数,fn对象是从Fn函数new出来的,这样fn对象就可以调用Fn.prototype中的属性。

  因为每个对象都有一个隐藏的属性——“__proto__”,这个属性引用了创建这个对象的函数的prototype

  即:fn.__proto__ === Fn. prototype

  这里的"__proto__"成为隐式原型

  隐式原型

  每个函数function都有一个prototype,即原型。这里再加一句话——每个对象都有一个__proto__,可成为隐式原型。__proto__用于指向创建它的构造函数的原型对象

  对象 person1 有一个 __proto__属性,创建它的构造函数是 Person,构造函数的原型对象是 Person.prototype ,所以:

  person1.__proto__ == Person.prototype

  又比如:obj这个对象本质上是被Object函数创建的,因此obj.__proto__=== Object.prototype

  在说明“Object.prototype”之前,先说一下自定义函数的prototype。自定义函数的prototype本质上就是和 var obj = {} 是一样的,都是被Object创建,所以它的__proto__指向的就是Object.prototype

  但是Object.prototype确是一个特例——它的__proto__指向的是null.

  至于为什么简单解释下:

  所有的构造器都来自于 Function.prototype,甚至包括根构造器ObjectFunction自身。所有构造器都继承了.Function.prototype.的属性及方法。如lengthcallapplybind

  console.log(typeof Function.prototype) // functionconsole.log(typeof Object.prototype)   // objectconsole.log(typeof Number.prototype)   // objectconsole.log(typeof Boolean.prototype)  // objectconsole.log(typeof String.prototype)   // objectconsole.log(typeof Array.prototype)    // objectconsole.log(typeof RegExp.prototype)   // objectconsole.log(typeof Error.prototype)    // objectconsole.log(typeof Date.prototype)     // objectconsole.log(typeof Object.prototype)   // object

  知道了所有构造器(含内置及自定义)的__proto__都是Function.prototype

  Function.prototype__proto__是谁呢?

  console.log(Function.prototype.__proto__ === Object.prototype) // true

  这说明所有的构造器也都是一个普通 JS 对象,可以给构造器添加/删除属性等。同时它也继承了Object.prototype上的所有方法:toStringvalueOfhasOwnProperty等。

  最后Object.prototypeproto是谁?

  Object.prototype.__proto__ === null // true

  已经到顶了,为null

  原型链

  概念

  访问一个对象的属性时,先在基本属性中查找,如果没有,再沿着__proto__这条链向上找

  javascript中的继承是通过原型链来体现的.

  传统原型语法

  function Foo() {}

  Foo.prototype.a = 100;

  Foo.prototype.b = 200;

  var f1 = new Foo();

  f1.a = 10;

  alert(f1.a);  //10

  alert(f1.b);  //200

  function Foo() {}

  var f1 = new Foo();

  f1.a = 10;

  Foo.prototype.a = 100;

  Foo.prototype.b = 200;

  alert(f1.a);  //10

  alert(f1.b);  //200

  对象字面量方法添加属性和方法的注意事项

  function Foo() {}

  Foo.prototype = {

  a: 100,

  b: 200

  }

  var f1 = new Foo();

  f1.a = 10;

  alert(f1.a); //10

  alert(f1.b); //200

  function Foo() {}

  var f1 = new Foo();

  f1.a = 10;

  Foo.prototype = {

  a: 100,

  b: 200

  }

  alert(f1.a);  //10

  alert(f1.b);  //undefined

  原型的属性和方法赋值要在,新建实例对象之前,不然无法获得原型的值和属性,alert返回相应的undefined

  重写原型对象问题

  接上面的例子讲,如果在实例上添加新属性,这个属性就会屏蔽原型对象中保存的同名属性,就是阻止访问了属性,而不是修改原型的属性。

  function Foo() {}

  var f1 = new Foo();

  f1.a = 10;

  Foo.prototype = {

  a: 100,

  b: 200

  }

  alert(f1.a);  //10

  alert(f1.b);  //undefined

  总结:重写原型对象切断了 现有原型 与任何之前 已经存在的对象实例 之间的关系,它们的引用的仍然是 最初的原型 

  End

  暂时总结到此,有些知识点没有讲到,可能需要大家自己去看书或查阅资料来理解,本人理解也有限,文中若有难以理解的还望大神换个方式来阐述。

 

 

来源:SegmentFault

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值