Giter VIP home page Giter VIP logo

Comments (11)

Charlotte777 avatar Charlotte777 commented on August 23, 2024 4

konw that,i will learn it when i have time

from blog.

yuxino avatar yuxino commented on August 23, 2024

主要伙伴@Hazlank是发了文章。然后跑过去看了。发现有些不明白就研究了一下。我只看了第一部分。第二部分没看。 所以只说第一部分的。感觉他写的有些鸡掰乱乱的,我自己改了一些排版。

from blog.

Hazlank avatar Hazlank commented on August 23, 2024

@Nbsaw prototype是function才有的属性

from blog.

yuxino avatar yuxino commented on August 23, 2024

所以看他的文章。先看第一个例子。

// 定义 SuperClass
function SuperClass(){
  this.val = true    
}
SuperClass.prototype.getVal = function(){
  return this.val
}
SuperClass.prototype.o={
  a:1
}

// 定义 SubClass
// 注意看这里把值设置成了false
function SubClass(){
  this.val = false
}

// 注意这里。重新把构造器的引用变回原来的SubClass
SubClass.prototype = new SuperClass();
SubClass.prototype.constructor = SubClass;

var sub = new SubClass();
sub.o.a = 2;
console.log(sub.getVal())

// 创建其他的SubClass实例
console.log(new SubClass().o.a) //2

类的原型对象的作用就是为类的原型添加共有方法。当子类的原型对象指向实例化一个父类的时候,再去实例化这个子类的时候,实例化后的对象里的__proto__就是我们父类的prototype对象,所以就能够访问到父类原型对象的方法和构造属性了。
但是有个缺点,因为prototype是指向对象,对象和基本值不一样,是引用,所以我们更改其中的属性也就是相当于更改父类的属性,就会相互影响
当然也可以通过父类的原型对象for-in循环复制到子类里,只要加上hasownproperty的判断就好啦。

第一个方案不好主要是引用的问题。

from blog.

Hazlank avatar Hazlank commented on August 23, 2024

第一个列子设成false只是想为了表明。构造函数的属性只会在当前作用域的构造函数的实例中创建,单独的。

from blog.

yuxino avatar yuxino commented on August 23, 2024

看第二个例子。仔细看这里没有用到prototype了,而是用了call

// 定义 SuperClass
function SuperClass(){
  this.val = true
  this.o={
    a:1    
  }
}

// 定义 SubClass
function SubClass(){
  SuperClass.call(this)
}

var sub1 = new SubClass()
console.log(sub1.val)

// 修改o
sub1.o.a=2

var sub2 = new SubClass();
console.log(sub2.o.a) //1

当我们实例化子类的时候,执行一遍父类的函数,利用call函数更改为子类的作用域,那么在this添加属性的时候就会对子类的实例化对象添加属性了,这样创建的实例就会有单独拥有一份属性了,而不会共用,但是这就违背了代码复用的原则。

考虑下面这个

// 定义 animal
function animal(){
  this.val = true
  this.o={
    a:1    
  }
}
animal.move = function(){console.log('move')}

// 定义 doge
function doge(){
  animal.call(this)
}

如果你实例化doge并调用move方法你会发现调用不了,因为这个move无法被继承。所以你可能改成这样子。

// 定义 animal
function animal(){
  this.val = true
  this.o={
    a:1    
  }
  this.move = function(){ console.log('move') }
}


// 定义 doge
function doge(){
  animal.call(this)
}

然后你再尝试调用。你会发现这是可以的。但是这不好。这会让这个构造函数变的非常庞大如果有很多方法属性的话。更加糟糕的是,如果你要创建很多个相同的实例。那么每次会建很多次move方法,这无疑很浪费性能。

from blog.

yuxino avatar yuxino commented on August 23, 2024

所以有第三种构造方法。组合构造

// 定义
SupClass = function(t){ this.t = t ; console.log('invoke'); }
SupClass.prototype.s = 's'

// 复用父类构造器
function SubClass(type){
  SupClass.call(this,type)
}

SubClass.prototype = new SupClass()

// 这样写相当于这样。让prototype接盘了SubClass的实例。
// SubClass.prototype = SupClass.__proto__

// 这样写不会破坏SubClass。但是再下次实例化SubClass的时候会多出来不必要的东西
//(具体看输出结果的__proto__里面多出来的部分)
var obj = new SubClass('t');
console.log(obj)

// 因为这么做相当于
// obj.__proto__ = SubClass.prototype = new SupClass()
// 所以会多出一个实例在__proto__里面
// 一个是实例化prototype的本身的对象。一个是在原型里边的new SupClass()

这样就能共用方法和享有自己的副本了,但是还是有点瑕疵,为什么呢?因为构造函数被调用了两次,你可以看到控制台会在初始化的时候输出了两次invoke。在初始化的时候会实例化一次构造器。并且在SubClass被实例化的时候又执行了一次。这无疑很多余。如果父构造器是一个比较复杂时间长的操作。这无疑加了不必要的创建时间。

from blog.

yuxino avatar yuxino commented on August 23, 2024

那么有第四种方法。

function inheritObject(o){
  function F(){}
  F.prototype = o;
  return new F();
}

// 定义
SupClass = function(t){ this.t = t; console.log('invoke'); }
SupClass.prototype.s = 's'

// 复用父类构造器
function SubClass(type){
  SupClass.call(this,type)
}
// 注意继承要提前写在前面。不然会覆盖掉掉子类的prototype
SubClass.prototype = inheritObject(SupClass.prototype);
SubClass.prototype.x = 'x'

SubClass.prototype.constructor = SubClass

new SubClass('t')

这个做法比上面那个好一点。不会多出来。更纯洁,开销更小。因为它只会在实例化SubClass的时候被执行。避免了不必要的创建。这主要是因为使用了f的空的构造器。

from blog.

Hazlank avatar Hazlank commented on August 23, 2024

书上还有其它几种方式,但我觉得没必要。

from blog.

yuxino avatar yuxino commented on August 23, 2024

@Hazlank TypeScript, Blade大法好

from blog.

Hazlank avatar Hazlank commented on August 23, 2024

@Nbsaw i konw that,i will learn it when i have time

from blog.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.