zoukankan      html  css  js  c++  java
  • 你不知道的JavaScript(上)this和对象原型(四)原型

    五章 原型

    1、[[ Prototype ]]

    JavaScript 中的对象有一个特殊的 [[Prototype]] 内置属性,其实就是对于其他对象的引用。几乎所有的对象在创建时 [[Prototype]] 属性都会被赋予一个非空的值。

    对于默认的 [[Get]] 操作来说,如果无法在对象本身找到需要的属性,就会继续访问对象
    的 [[Prototype]] 链:

    1 var anotherObject = {
    2 a:2
    3 };
    4 // 创建一个关联到 anotherObject 的对象
    5 var myObject = Object.create( anotherObject );
    6 myObject.a; // 2

    还有另外一种方法,就是使用for..in遍历对象时原理,和查找[[ Prototype ]]链想死,任何可以通过原型链访问到的属性都会被枚举。使用in操作符来检查属性在对象中是否存在也会查找对象的整条原型链(无论属性是否可枚举)

    var anotherObject = {
    a:2
    };
    // 创建一个关联到 anotherObject 的对象
    var myObject = Object.create( anotherObject );
    for (var k in myObject) {
    console.log("found: " + k);
    }
    // found: a
    ("a" in myObject); // true

    2、“构造函数“

    在 JavaScript 中对于“构造函数”最准确的解释是,所有带 new 的函数调用。函数不是构造函数,但是当且仅当使用 new 时,函数调用会变成“构造函数调用”

    1 function NothingSpecial() {
    2 console.log( "Don't mind me!" );
    3 }
    4 var a = new NothingSpecial();
    5 // "Don't mind me!"
    6 a; // {}

    3、原型继承【重点】

    图中由下到上的箭头表明这是委托关联,不是复制操作。

    典型的“原型风格”,例子如下:

     1 function Foo(name) {
     2 this.name = name;
     3 }
     4 Foo.prototype.myName = function() {
     5 return this.name;
     6 };
     7 function Bar(name,label) {
     8 Foo.call( this, name );
     9 this.label = label;
    10 }
    11 // 我们创建了一个新的 Bar.prototype 对象并关联到 Foo.prototype
    12 Bar.prototype = Object.create( Foo.prototype );
    13 // 注意!现在没有 Bar.prototype.constructor 了
    14 // 如果你需要这个属性的话可能需要手动修复一下它
    15 Bar.prototype.myLabel = function() {
    16 return this.label;
    17 };
    18 var a = new Bar( "a", "obj a" );
    19 a.myName(); // "a"
    20 a.myLabel(); // "obj a"

    核心部分就是语句 Bar.prototype = Object.create( Foo.prototype ) 。调用Object.create(..) 会凭空创建一个“新”对象并把新对象内部的 [[Prototype]] 关联到你指定的对象(本例中是 Foo.prototype )。但是 Object.create(..)唯一的缺点就是需要创建一个新对象然后把旧对象抛弃掉,不能直接修改已有的默认对象。

    ES6添加了一个辅助函数Object.setPrototypeOf(..) ,可以用标准并且可靠的方法来修改关联。

    对比一下两种关联的方法

    1 // ES6 之前需要抛弃默认的 Bar.prototype
    2 Bar.ptototype = Object.create( Foo.prototype );
    3 // ES6 开始可以直接修改现有的 Bar.prototype
    4 Object.setPrototypeOf( Bar.prototype, Foo.prototype );

    4、检查“类”的关系

    寻找对象a委托的对象,也就是检查一个实例(js中的对象)的继承祖先(js中的委托关联)被称为内省(或者反射)

    例子

    1 function Foo() {
    2 // ...
    3 }
    4 Foo.prototype.blah = ...;
    5 var a = new Foo();

    方法一  (instanceof)

    instanceof 操作符的左操作数是一个普通的对象,右操作数是一个函数。 instanceof 回答的问题是:在 a 的整条 [[Prototype]] 链中是否有指向 Foo.prototype 的对象?可是,这个方法只能处理对象( a )和函数(带 .prototype 引用的 Foo )之间的关系。如果你想判断两个对象(比如 a 和 b )之间是否通过 [[Prototype]] 链关联,只用 instanceof无法实现

    a instanceof Foo; // true

    方法二  

    在本例中,我们实际上并不关心(甚至不需要) Foo ,我们只需要一个可以用来判断的对象(本例中是 Foo.prototype )就行。 isPrototypeOf(..) 回答的问题是:在 a 的整条 [[Prototype]] 链中是否出现过 Foo.prototype ?

    Foo.prototype.isPrototypeOf( a ); // true

     5、创建关联

    Object.create() 的polyfill代码。这段 polyfill 代码使用了一个一次性函数 F ,我们通过改写它的 .prototype 属性使其指向想要关联的对象,然后再使用 new F() 来构造一个新对象进行关联。

    1 if (!Object.create) {
    2   Object.create = function(o) {
    3   function F(){}
    4   F.prototype = o;
    5   return new F();
    6   };
    7 }

     第六章 行为委托

     重点:对象关联

     1 Foo = {
     2               init:function(who){
     3                   this.me=who;
     4               },
     5               identify:function(){
     6                   return "i am "+this.me;
     7               }
     8           };
     9           Bar = Object.create(Foo);
    10           Bar.speak = function(){
    11               console.log("hello"+this.identify()+".");
    12           }
    13           var b1 = Object.create(Bar);
    14           b1.init("b1");
    15           var b2 = Object.create(Bar);
    16           b2.init("b2");
    17           b1.speak();
    18           b2.speak();

    ES6 使用更好的对象字面形式的语法和简洁方法

     1 var AuthController = {
     2 errors: [],
     3 checkAuth() {
     4 // ...
     5 },
     6 server(url,data) {
     7 // ...
     8 }
     9 // ...
    10 };
    11 // 现在把 AuthController 关联到 LoginController
    12 Object.setPrototypeOf( AuthController, LoginController );
  • 相关阅读:
    MVC3、如何应用EntityFramework 连接MySql 数据库 Kevin
    DEV EXPRESS Summary Footer 不显示 Kevin
    装饰模式 Kevin
    Dev 控件 GridControl 控件 二次绑定数据源的问题。 Kevin
    System.InvalidOperationException 异常 Kevin
    LINQ to XML Kevin
    代理模式——代码版“吊丝的故事” Kevin
    VS2012 中的设备 面板 Kevin
    maven 学习笔记(三)创建一个较复杂的 eclipse+android+maven 工程
    maven 学习笔记(一)eclipse+android+maven
  • 原文地址:https://www.cnblogs.com/chorkiu/p/10115683.html
Copyright © 2011-2022 走看看