Penjelasan terperinci tentang prinsip kemahiran Javascript chain_javascript

WBOY
Lepaskan: 2016-05-16 15:21:42
asal
1414 orang telah melayarinya

Artikel ini menganalisis prinsip rantaian prototaip Javascript melalui contoh. Kongsikan dengan semua orang untuk rujukan anda, butirannya adalah seperti berikut:

1. Rantaian prototaip JavaScript

ECMAScript menerangkan konsep rantaian prototaip dan menggunakan rantaian prototaip sebagai kaedah utama untuk melaksanakan pewarisan. Idea asas ialah menggunakan prototaip untuk membenarkan satu jenis rujukan mewarisi sifat dan kaedah jenis rujukan yang lain. Dalam JavaScript, atribut __proto__ digunakan untuk mewakili rantai prototaip objek. Apabila mencari sifat objek, JavaScript berjalan ke atas rantaian prototaip sehingga ia menemui sifat dengan nama tertentu!

Sebagai contoh, kami kini mempunyai kod berikut:

Melanjutkan kelas Objek dan menambah kaedah Klon dan Lanjutkan

/*扩展Object类,添加Clone,JS实现克隆的方法*/
Object.prototype.Clone = function(){
  var objClone;
  if (this.constructor == Object){
    objClone = new this.constructor(); 
  }else{
    objClone = new this.constructor(this.valueOf()); 
  }
  for(var key in this){
    if ( objClone[key] != this[key] ){ 
      if ( typeof(this[key]) == 'object' ){ 
        objClone[key] = this[key].Clone();
      }else{
        objClone[key] = this[key];
      }
    }
  }
  objClone.toString = this.toString;
  objClone.valueOf = this.valueOf;
  return objClone; 
}
/*扩展Object类,添加Extend方法来实现JS继承, 目标对象将拥有源对象的所有属性和方法*/
Object.prototype.Extend = function (objDestination, objSource) {
  for (var key in objSource) {
    if (objSource.hasOwnProperty(key) && objDestination[key] === undefined) {
      objDestination[key] = objSource[key];
    }
  }
  return objDestination;
}

Salin selepas log masuk

Tentukan kelas Orang

/*定义一个Person类*/
 function Person(_name,_age){
   this.name = _name;
   this.age = _age;
}

Salin selepas log masuk

Dalam JavaScript, kelas Object ialah kelas induk bagi semua kelas, jadi kelas Person mewarisi daripada kelas Object dan mewarisi semua sifat awam dan kaedah awam kelas Object, termasuk Clone dan Extend yang baru ditambah kaedah kelas Objek

Anda boleh menggunakan kod berikut untuk membuktikan bahawa kelas Orang memang mewarisi kelas Objek

document.write("<pre class="brush:php;toolbar:false">");
var p = new Person("孤傲苍狼",24);//创建一个人,名字是孤傲苍狼
var cloneP = p.Clone();//p调用在Object类中定义的Clone方法来克隆自己,如果能得到一个cloneP,那就证明了Person类确实是继承了Object类,所以就拥有了Clone
document.writeln("p是使用Person类以构造函数的方式创建出来的对象,p.name = "+p.name+",p.age = "+p.age);
document.writeln("cloneP是p调用Clone方法克隆出来的对象,cloneP.name = "+cloneP.name+",cloneP.age = "+cloneP.age);
document.writeln("cloneP对象和p对象是两个相互独立的对象,这两个对象的内存地址肯定是不相等,p == cloneP的结果是:"+(p == cloneP));
cloneP.name="白虎神皇";//修改cloneP的名字
document.writeln("cloneP的name被修改了,cloneP.name = "+cloneP.name);
document.writeln("cloneP的name修改了,但是不影响到p,p.name = "+p.name);
document.write("
");
Salin selepas log masuk

Hasil jalankan:

Kemudian kelas Orang mewarisi kelas Objek melalui kaedah Shenma Ia diwarisi menggunakan kaedah prototaip (prototye):

/*定义一个Person类*/
function Person(_name,_age){
   this.name = _name;
   this.age = _age;
}
Person.prototype = new Object();//让Person类继承Object类

Salin selepas log masuk

Memandangkan JavaScript menetapkan bahawa mana-mana kelas mewarisi daripada kelas Objek, jadi "Person.prototype = new Object();//Let the Person class mewarisi kelas Object " Walaupun kita tidak menulis ia, saya rasa enjin JavaScript Ia juga akan menambah ayat ini secara automatik untuk kita, atau gunakan "Person.prototype = Object.prototype;" untuk membenarkan kelas Person mewarisi kelas Objek. "Person.prototype = new Object();", sebenarnya, ini bersamaan dengan objek Object sebagai prototaip Orang, yang bersamaan dengan menyalin sifat dan kaedah objek Objek kepada Orang .

2. Cara pengendali baharu berfungsi

Mari kita lihat sekeping kod ini dahulu:

Salin kod Kod adalah seperti berikut:
var p = new Person("lonewolf",24);// Buat Orang bernama Lone Ao Canglang

Sekeping kod yang sangat mudah, mari kita lihat apa yang baru ini lakukan? Kita boleh membahagikan proses baharu kepada tiga langkah berikut:

1.var p={};

2. p.__proto__=Person.prototype;, tetapkan atribut __proto__ objek p kepada Person.prototype

3.Person.call(p,"lonewolf",24);

Kuncinya terletak pada langkah kedua, mari kita buktikan:

var p = new Person("孤傲苍狼",24);//创建一个人,名字是孤傲苍狼
alert("p.__proto__ === Person.prototype的结果是:"+(p.__proto__ === Person.prototype));

Salin selepas log masuk

Hasil berjalan di bawah Firefox ialah:

Kod ini akan kembali benar. Jelaskan bahawa langkah 2 kami adalah betul.

Nota: Atribut __proto__ hanya boleh diakses secara umum dalam pelayar Firefox atau Chrome, oleh itu, penyemak imbas lain berdasarkan kernel IE tidak akan kembali benar.

Jadi apakah itu __proto__? Mari bercakap secara ringkas di sini. Setiap objek akan memulakan atribut di dalamnya, iaitu __proto__ Apabila kita mengakses atribut objek, jika atribut ini tidak wujud di dalam objek, maka dia akan pergi ke __proto__ untuk mencari atribut, __proto__ ini akan mempunyai sendiri. __proto__, jadi saya terus mencarinya, yang biasanya kita panggil konsep rantaian prototaip.

Menurut piawaian, __proto__ tidak terbuka kepada umum, yang bermaksud ia adalah atribut peribadi. Atribut __proto__ tidak boleh diakses di bawah IE, tetapi enjin Firefox mendedahkannya dan menjadikannya sebagai atribut awam dan ditetapkan secara luaran.

Baiklah, konsepnya jelas, mari kita lihat kod berikut:

<script type="text/javascript">
    var Person = function () { };
    Person.prototype.Say = function () {
      alert("Person say");
    }
    var p = new Person();
    p.Say();
</script>

Salin selepas log masuk

Kod ini sangat mudah. ​​Mari lihat sebab p boleh mengakses Kata Orang.

Pertama sekali

Salin kod Kod adalah seperti berikut:
var p=new Person();

Boleh disimpulkan bahawa

Salin kod Kod adalah seperti berikut:
p.__proto__=Person.prototype

Jadi apabila kita memanggil p.Say(), pertama sekali, tiada atribut Say dalam p, jadi dia perlu mencarinya dalam __proto__nya, iaitu Person.prototype, dan kami mentakrifkannya di atas

Person.prototype.Say=function(){
    alert("Person say");
};

Salin selepas log masuk

于是,就找到了这个方法。

接下来,让我们看个更复杂的。

<script type="text/javascript">
    var Person = function () { };
    Person.prototype.Say = function () {
      alert("Person say");
    }
    Person.prototype.Salary = 50000;
    var Programmer = function () { };
    Programmer.prototype = new Person();//让程序员类从人这个类继承
    Programmer.prototype.WriteCode = function () {
      alert("programmer writes code");
    };
    Programmer.prototype.Salary = 500;
    var p = new Programmer();
    p.Say();
    p.WriteCode();
    alert(p.Salary);
</script>

Salin selepas log masuk

我们来做这样的推导:

复制代码 代码如下:
var p=new Programmer();

可以得出

复制代码 代码如下:
p.__proto__=Programmer.prototype;

而在上面我们指定了

复制代码 代码如下:
Programmer.prototype=new Person();

我们来这样拆分,

var p1=new Person();
Programmer.prototype=p1;

Salin selepas log masuk

那么:

p1.__proto__=Person.prototype;
Programmer.prototype.__proto__=Person.prototype;

Salin selepas log masuk

由根据上面得到

复制代码 代码如下:
p.__proto__=Programmer.prototype

可以得到:

复制代码 代码如下:
p.__proto__.__proto__=Person.prototype

好,算清楚了之后我们来看上面的结果,p.Say()。由于p没有Say这个属性,于是去 p.__proto__,也就是Programmer.prototype,也就是p1中去找,由于p1中也没有Say,那就去 p.__proto__.__proto__,也就是Person.prototype中去找,于是就找到了Say方法。这也就是原型链的实现原理。

以下代码展示了JS引擎如何查找属性:

function getProperty(obj, prop) {
  if (obj.hasOwnProperty(prop))
    return obj[prop];
  else if (obj.__proto__ !== null)
    return getProperty(obj.__proto__, prop);//递归
  else
    return undefined;
}

Salin selepas log masuk

范例:查找p对象的Say方法

<script type="text/javascript">
  /*查找obj对象的prop属性*/
   function getProperty(obj, prop) {
    if (obj.hasOwnProperty(prop))
      return obj[prop];
    else if (obj.__proto__ !== null)
      return getProperty(obj.__proto__, prop);//递归
    else
      return undefined;
  }
  var Person = function () { };//定义Person类
  Person.prototype.Say = function () {
    alert("Person say");
  }
  Person.prototype.Salary = 50000;
  var Programmer = function () { };//定义Programmer类
  //Programmer.prototype = new Person();//让程序员类从人这个类继承,写法一
  Programmer.prototype = Person.prototype;//让程序员类从人这个类继承,写法二
  Programmer.prototype.WriteCode = function () {
    alert("programmer writes code");
  };
  Programmer.prototype.Salary = 500;
  var p = new Programmer();
  var SayFn = getProperty(p,"Say");//查找p对象的Say方法
  SayFn.call(p);//调用找到的Say方法
</script>

Salin selepas log masuk

在火狐下的运行结果:

其实prototype只是一个假象,他在实现原型链中只是起到了一个辅助作用,换句话说,他只是在new的时候有着一定的价值,而原型链的本质,其实在于__proto__。

希望本文所述对大家JavaScript程序设计有所帮助。

Label berkaitan:
sumber:php.cn
Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Tutorial Popular
Lagi>
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan
Tentang kita Penafian Sitemap
Laman web PHP Cina:Latihan PHP dalam talian kebajikan awam,Bantu pelajar PHP berkembang dengan cepat!