Rumah  >  Artikel  >  hujung hadapan web  >  Perbincangan: JavaScript ECAMScript5 ciri baharu dapatkan/tetapkan kemahiran accessor_javascript

Perbincangan: JavaScript ECAMScript5 ciri baharu dapatkan/tetapkan kemahiran accessor_javascript

WBOY
WBOYasal
2016-05-16 15:02:131133semak imbas

Pengenalan kepada EcmaScript5

Pertama sekali, kita mesti faham bahawa ECMAScript adalah kuda ajaib versi. Skrip penyemak imbas semuanya melakukan perkara mereka sendiri, dan semua orang memahami kekeliruan ini, jadi isu penyeragaman telah diletakkan dalam agenda. Pada tahun 1997, satu cadangan berdasarkan JavaScript 1.1 telah dikemukakan kepada Persatuan Pengeluar Komputer Eropah (Persatuan Pengeluar Komputer Eropah Pada akhirnya, semua orang menyanyi dan menari untuk menghasilkan ECMA-262, satu standard bahasa skrip baru yang dipanggil ECMAScript . Pada tahun berikutnya, ISO/IEC (Organisasi Antarabangsa untuk Standardisasi dan Suruhanjaya Elektroteknikal Antarabangsa) juga menerima pakai ECMAScript sebagai piawaian Sejak itu, dunia telah aman menggunakan ECMAScript sebagai asas untuk pelaksanaan JavaScript masing-masing , ia hanya asas dan tidak diikuti sepenuhnya. Jika tidak, Kami juga tidak akan mempunyai banyak isu keserasian penyemak imbas.

Apakah itu ECMAScript5? Seperti namanya, ia adalah versi kelima bagi perkara aneh ini seperti iPhone5 Yang biasa kami gunakan sekarang ialah ECMAScript3 Berbanding dengan dua versi pertama, versi ini adalah bahasa pengaturcaraan sebenar dan bukannya mainan, dan ia telah menjadi sangat popular.

Teks:

Pemahaman saya sebelum ini tentang get/set adalah salah. Saya fikir get set ialah kaedah sifat objek. Saya juga mempunyai banyak soalan selepas membaca blog orang lain Hari ini saya melakukan banyak ujian pada sistem dan akhirnya mengetahuinya. (Saya telah lulus ujian dengan membaca buku dan menulis demo. Jika terdapat sebarang kesilapan, anda dialu-alukan untuk mengkritik dan membetulkan saya)

Aksesori get/set bukan sifat objek, tetapi ciri sifat. Setiap orang mesti membezakan dengan jelas. Sifat hanya digunakan secara dalaman, jadi ia tidak boleh diakses terus daripada JavaScript. Untuk menunjukkan atribut, nilai dalaman disertakan dalam dua set kurungan segi empat sama, seperti [[Nilai]].

1 Mari kita perkenalkan secara ringkas ciri-ciri atribut ini (ini ialah pengesahan ringkas)

(1) Atribut data - mengandungi lokasi nilai data. Nilai boleh dibaca dan ditulis ke lokasi ini.

Atribut data mempunyai empat ciri yang menggambarkan tingkah lakunya:

[[Boleh Dikonfigurasikan]]: Sama ada ia boleh dikonfigurasikan

[[Enumerable]]: Sama ada ia boleh dihitung

[[Boleh Ditulis]]: Sama ada ia boleh dibaca

[[Nilai]]: Nilai atribut 

(2) Atribut atribut accessor - tidak mengandungi nilai data, mengandungi fungsi getter dan setter (dua fungsi ini tidak diperlukan)

Sifat aksesori juga mempunyai empat ciri yang menggambarkan tingkah laku mereka:

[[Boleh Dikonfigurasikan]]: Sama ada ia boleh dikonfigurasikan

[[Enumerable]]: Sama ada ia boleh dihitung

[[Dapatkan]]: Fungsi dipanggil semasa membaca sifat, lalai tidak ditentukan

[[Set]]: Fungsi dipanggil semasa menulis atribut, lalainya tidak ditentukan 

2 Di sini kami memfokuskan pada [[Dapatkan]]/[[Set]], iaitu apa yang kami panggil sebagai pengakses get/set

Mula-mula mari kita bincangkan tentang ciri gelagat pengakses get/set yang disebut dalam buku: pengakses get/set tidak perlu ditakrifkan dan ia boleh membaca dan menulis nilai atribut tanpa mentakrifkannya. Anda juga boleh menentukan hanya satu. Jika hanya get ditakrifkan, atribut yang diterangkan hanya boleh dibaca, bukan boleh ditulis. Jika hanya set ditakrifkan, atribut yang diterangkan hanya boleh ditulis, tidak boleh dibaca.

(1) Kaedah get set asal kami adalah seperti ini:

function Foo(val){
var value=val;
this.getValue=function(){
return value;
};
this.setValue=function (val){
value=val;
};
}
var obj=new Foo("hello");
alert(obj.getValue());//"hello"
obj.setValue("hi");
alert(obj.getValue());//"hi" 

Kod di atas hanyalah kaedah get set yang dilaksanakan menggunakan skop penutupan Ambil perhatian bahawa kaedah tersebut ialah kaedah atribut objek contoh, bukan ciri atribut. Jika ia tidak ditakrifkan, nilai nilai
tidak akan dapat diakses.

function Foo(val){
var value=val;
/* this.getValue=function(){
return value;
};
this.setValue=function (val){
value=val;
};
*/
}
var obj=new Foo("hello");
alert( obj.value);//undefined

Contoh berikut juga merupakan kaedah sifat objek, bukan ciri sifat.

var obj={
name:"john",
get:function (){
return this.age;
}//只定义了get ,没有定义set,但是仍然可以读,写,name属性,即使这里是age
//这里这样定义的方法不会影响属性的get,set 特性。只是普通的对象属性
};
alert(obj.name);//john 可读
obj.name="jack";//可写
alert(obj.name);//jack 

(2) Dapatkan/tetapkan pengakses sebagai ciri atribut pengakses.

Sekali lagi, ia bukan sifat objek, ia menentukan sama ada dan bagaimana sifat boleh dibaca dan ditulis. Tidak mengapa jika anda tidak menetapkannya, ia akan sama seperti membaca dan menulis biasa (atribut boleh dibaca

Akses tulis, baca dan tulis ialah nilai atribut itu sendiri)

Untuk menukar sifat get/set atribut, terdapat dua cara:

a. Hanya gunakan Object.defineProperty()

var object={
_name:"Daisy" 
};
Object.defineProperty(object,"name",{//这里的方法名name,就表示定义了一个name属性(因此才能通过object.name访问),只定义了getter访问器,没有定义[[value]]值
get:function (){//只定义了get 特性,因此只能读不能写
return this._name;
}
});
alert(object.name);//"Daisy"
object.name="jack";//只定义了getter访问器,因此写入失效
alert(object.name);//"Daisy" 

Perhatikan bahawa nama sifat dalam Object.defineProperty(object, pro, {}) mesti sepadan dengan sifat yang diakses oleh object.pro

b. Hanya gunakan kata kunci get set:

var object={
_name:"Daisy",
get name(){//这里的方法名name ,就表示定义了一个name属性(因此才能通过object.name访问),只定义了getter访问器,没有定义[[value]]值
return this._name;
}//get,set方法只是属性的特性 ,不是对象方法,决定属性能否、怎么读写
};
alert(object.name);// Daisy这里去掉下划线 方法就是Daisy ;加上就是undefined
object.name="jack";//只定义了getter访问器,因此只能读不能写
alert(object.name);//Daisy 

以上两种方法等效。注意的是以上两种方法object对象当中都将有有两个属性:_name(有初始值) name(无初始值),通过浏览器控制台可以看到

那么这个name属性实在什么时候定义的呢?我们知道Object.defineProperty(object,pro,{})可以给对象定义一个新属性pro,既然get pro(){}/set pro(){}和Object.defineProperty(object,pro,{})等效,则也会定义一个新属性pro .这就是为什么object里面有两个属性的原因。

(3)在此篇文章中网络之美 JavaScript中Get和Set访问器的实现代码关于标准标准的Get和Set访问器的实现:引发的思考

我自己也写了一个一样的例子

function Foo(val){
this.value=val;//定义了value属性 并没有定义_value
}
Foo.prototype={
set value(val){//注意方法名和属性名相同,在prototype里定义了value属性
this._value=val;
},
get value(){//方法名和属性名相同,在prototype里面定义了value属性和它的get 特性
return this._value;
}
}; //访问器返回和设置的都是_name,这里并没有定义_name属性为什么也可以读可以写????     
var obj=new Foo("hello");     
alert(obj.value);//"hello"     
obj.value="yehoo";     
alert(obj.value);//"yehoo" 

为了解决以上这个疑问,做了很多测试,我们一一来看:

先看这个例子,在prototype里面只定义get 特性,在obj.value读value属性时,在实例里面寻找没有,然后在原型里面找到,调用的是原型的get方法,只能读不能写

function Foo(val){
this._value=val;//这里 的属性是带下划线的,初始化实例对象的_value属性,_value属性可读可写
}
Foo.prototype={
// set value(val){//注意方法名和属性名相同,在prototype里定义了value属性
// this._value=val;
// },
get value(){//方法名和属性名相同,在prototype里面定义了value属性和它的get 特性
return this._value;
}
}; 
var obj=new Foo("hello");
alert(obj.value);//hello 访问的是prototype里面的value 属性
obj.value="yehoo";//只定义了name 属性的get 特性,因此只能读不能写,写入失效
alert(obj.value);//hello 

如果构造函数里面this._value 去掉下划线,在prototype里面定义的value属性,定义了get 特性。依然可以控制value属性的读写 。也就是说obj.value访问属性时,会调用get方法,先在对象本身寻找,如果没有,再到prototype寻找,如果都没有才算没有定义,默认的既可读又可写

function Foo(val){
this.value=val;//在原型里面只定义了value的get特性,因此这里写入失效
}
Foo.prototype={
// set value(val){//注意方法名和属性名相同,在prototype里定义了value属性的set特性
// this._value=val;
//},
//value:"hah",//即使手动写入value值,由于get方法返回的是this._value,因此也不能正确读取value:"hah"
//只要声明了get pro (){}和set pro (){}属性就都能读能写,但是如果函数定义错误,依然不能按要求访问到正确的属性值
get value(){//方法名和属性名相同,在prototype里面定义了value属性和它的get 特性
return this._value;
}
}; 
var obj=new Foo("hello");//"hello"没有写入成功
alert(obj.value);//undefined 
obj.value="yehoo";//只定义了get 特性,因此只能读不能写,写入失效
alert(obj.value);//undefined 

为了证明上面例子是可读不可写的:手动写入_value:"hah",就可以读取value 但不能写入。

function Foo(val){
this.value=val;//在原型里面只定义了value的get特性,因此这里写入失效
}
Foo.prototype={
// set value(val){//注意方法名和属性名相同,在prototype里定义了value属性的set特性
// this._value=val;
//},
_value:"hah",//即使手动写入value值,由于get方法返回的是this._value,因此也不能正确读取value:"hah"
//只要声明了get pro (){}和set pro (){}属性就都能读能写,但是如果函数定义错误,依然不能按要求访问到正确的属性值
get value(){//方法名和属性名相同,在prototype里面定义了value属性和它的get 特性
return this._value;
}
}; 
var obj=new Foo("hello");//"hello"没有写入成功
alert(obj.value);//"hah" 
obj.value="yehoo";//只定义了get 特性,因此只能读不能写,写入失效
alert(obj.value);//"hah" 

如果手动写入的是value:"hah",那么可以争取读取value的值吗?由于get方法返回的this._value并没有定义,obj.value读取value值调用get value(){}方法失效,但是value仍然不能写入。

function Foo(val){
this.value=val;//在原型里面只定义了value的get特性,因此这里写入失效
}
Foo.prototype={
// set value(val){//注意方法名和属性名相同,在prototype里定义了value属性的set特性
// this._value=val;
//},
value:"hah",//即使手动写入value值,由于get方法返回的是this._value,因此也不能正确读取value:"hah"
//只要声明了get pro (){}和set pro (){}属性就都能读能写,但是如果函数定义错误,依然不能按要求访问到正确的属性值
get value(){//方法名和属性名相同,在prototype里面定义了value属性和它的get 特性
return this._value;
}
}; 
var obj=new Foo("hello");//"hello"没有写入成功
alert(obj.value);//undefined 读取失效 因为只要obj.value就会调用get ,而get返回的是this._value,没有这个值,因此undefined
obj.value="yehoo";//只定义了get 特性,因此只能读不能写,写入失效
alert(obj.value);//undefined 

再看这个例子,get set 都定义了,但是返回没有定义的this._value。可以发现value既可读又可写。去掉原型里面的get set方法,依然可读可写

function Foo(val){
this.value=val;
}
Foo.prototype={
set value(val){
this._value=val;
},
get value(){
return this._value;
}
}; 
var obj=new Foo("hello");
alert(obj.value);//hello 
obj.value="yehoo";
alert(obj.value);//yehoo 
function Foo(val){
this.value=val;
}
//和平时的操作是一样的了,就是回到了不定义get /set访问器特性的默认状态
var obj=new Foo("hello");
alert(obj.value);//hello 
obj.value="yehoo";
alert(obj.value);//yehoo 

总结

只声明了get pro(){}属性 可读不可写;

只声明 set pro(){}属性可写不可读。

如果都不声明,属性可读可写;

如果都声明就按照,get set 定义的方法,读写;

如果都声明了,但是定义的读写方法不能正确读写,get/set失效。变成默认的可读可写

在prototype里面定义的value属性,定义了get 特性。依然可以控制value属性的读写 。也就是说obj.value访问属性时,会调用get方法,先在对象本身寻找,如果没有,再到prototype寻找,如果都没有才算没有定义,默认的既可读又可写。

补充:

不管是用get pro(){}/set pro (){} 

还是用Object.defineProperty(object,pro,{


         get:function (){
           return this._name;
           } });

pro不能和 return this. 后面的属性一样,不然会报下面的错误:(具体我也不知道为什么,好像是自身调用引起的栈溢出)

经大神指正,明白为什么这里报错:在get value(){}方法里返回 this.value,就会又去调用value的get 方法,因此陷入死循环,造成方法栈溢出。

Kenyataan:
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