Web开发——JavaScript基础(继承)
Posted zyjhandsome
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Web开发——JavaScript基础(继承)相关的知识,希望对你有一定的参考价值。
当前参考学习《JavaScript语言精粹》
在基于类的语言中,对象是类的实例,并且类可以从另一个类继承。javascript是一门基于原型的语言,这意味着对象直接从其它对象继承。
1、伪类
当一个函数对象被创建时,Function构造器产生的函数对象会运行类似这样的一些代码:
1 this.prototype = {constructor: this};
新函数对象被赋予一个prototype属性,其值是包含一个constructor属性且属性值为该新函数对象。该prototype对象是存放继承特征的地方。因为JavaScript语言没有提供一种方法确定哪个函数式打算用来作构造器的,所以每个函数都会得到一个prototype对象。constructor属性没什么用。重要的是prototype对象。
我们可以定义一个构造器并扩充它的原型:
1 var Mammal = function (name) { 2 this.name = name; 3 }; 4 Mammal.prototype.get_name = function () { 5 return this.name; 6 }; 7 Mammal.prototype.says = function () { 8 return this.saying || ‘‘; 9 }; 10 11 // 现在可以构造一个实例 12 var myMammal = new Mammal("Herb the Mammal"); 13 var name = myMammal.get_name(); 14 console.log(name);
输出结果:Herb the Mammal
我们可以构造另一个伪类来继承Mammel,这是通过定义它的constructor函数并替换它的prototype为一个Mammal的实例来实现的:
1 var Mammal = function (name) { 2 this.name = name; 3 }; 4 Mammal.prototype.get_name = function () { 5 return this.name; 6 }; 7 Mammal.prototype.says = function () { 8 return this.saying || ‘‘; 9 }; 10 11 // // 现在可以构造一个实例 12 // var myMammal = new Mammal("Herb the Mammal"); 13 // var name = myMammal.get_name(); 14 // console.log(name); 15 16 var Cat = function (name) { 17 this.name = name; 18 this.saying = ‘meow‘; 19 }; 20 // 替换Cat.prototype为一个新的Mammal实例 21 Cat.prototype = new Mammal(); 22 // 扩充新原型对象,增加purr和get_name方法 23 Cat.prototype.purr = function (n) { 24 var i, s = ‘‘; 25 for (i = 0; i < n; i++) { 26 if (s) { 27 s += ‘-‘; 28 } 29 s += ‘r‘; 30 } 31 return s; 32 }; 33 Cat.prototype.get_name = function () { 34 return this.says() + ‘ ‘ + this.name + ‘ ‘ + this.says(); 35 }; 36 37 var myCat = new Cat(‘Henrietta‘); 38 var says = myCat.says(); 39 console.log(says); // ‘meow‘ 40 var purr = myCat.purr(5); 41 console.log(purr); // r-r-r-r-r 42 var name = myCat.get_name(); 43 console.log(name); // ‘meow Henrietta meow‘
输出结果:
1 r-r-r-r-r 2 meow Henrietta meow
伪类模式本意是想向面向对象靠拢,但它看起来格格不入。我们可以隐藏一些丑陋的细节,这是通过使用method方法定义一个inherits方法来实现的。
2、对象说明符(属性特性)
有时候,构造器要接受一大串的参数。这可能是令人烦恼的,因为要记住参数的顺序可能非常困难。在这种情况下,如果我们在编写构造器时使其接受一个简单的对象说明符可能会更加友好。那个对象包含了将要构建的对象规格说明。所以,语气这样写:
1 var myObject = maker(f, l, m, c, s);
不如这么写:
1 var myObject = maker({ 2 first: f, 3 last: l, 4 state: s, 5 city: c 6 });
现在多个参数可以任意顺序排列,如果构造器会聪明地使用默认值,一些参数可以忽略掉,并且代码也更容易阅读。
举例说明(参考https://www.cnblogs.com/qiutianlaile/p/7829496.html):
先创建一个对象:
1 var person = { 2 name: "Nicholas", 3 _job: "Software Engineer", 4 sayName: function () { 5 console.log(this.name); 6 }, 7 get job() { 8 return this._job; 9 }, 10 set job(newJob) { 11 this._job = newJob; 12 } 13 };
在这个对象中,我们定义了一个name属性和一个_job属性;至于set和get开头的两处代码,它们共同定义了一个属性job。明显属性job和_job、name的属性是不同的。是的,JavaScript中的对象由两种不同类型的属性:数据属性和访问器属性。name和_job是数据属性,job是访问器属性数据属性和访问器属性最大的不同在于:当访问一个访问器属性时,得到get后面函数的返回值;给访问器属性赋值时,执行的是set后面的函数,这个函数以赋的值为参数:
1 console.log(person.name); // 输出Nicholas 2 console.log(person._job); // "Software Engineer" 3 console.log(person.job); // "Software Engineer" 4 person.job = ‘Coder‘; 5 console.log(person.job); // Coder 6 console.log(person._job); // Coder
上述代码中,在set函数中我们通过this改变了_job的值(this指向person这个对象)。
我们在创建person对象时没有为它的属性们直接指定特征值,JavaScript自动为它们创建了属性特性。在ES3中属性特性不可访问,但是ES5中属性的特性可以通过Object.getOwnPropertyDescriptors或Object.getOwnPropertyDescriptor得到:
1 var descriptors= Object.getOwnPropertyDescriptors(person); 2 console.log(descriptors);
输出结果如下(descriptors的属性):
1 { name: 2 { value: ‘Nicholas‘, 3 writable: true, 4 enumerable: true, 5 configurable: true }, 6 _job: 7 { value: ‘Coder‘, 8 writable: true, 9 enumerable: true, 10 configurable: true }, 11 sayName: 12 { value: [Function: sayName], 13 writable: true, 14 enumerable: true, 15 configurable: true }, 16 job: 17 { get: [Function: get job], 18 set: [Function: set job], 19 enumerable: true, 20 configurable: true } }
数据属性
数据属性的描述符的有四个属性分别是:
- value:包含这个属性的数据值。读取属性的时候,从这个位置读;写入属性值的时候,把新值保存在这个位置。默认为undefined。
- writable:表示能否修改属性的值。是一个bool值,默认为true。
- enumerable:属性是否可枚举,即能否通过for-in循环返回属性。是一个bool值,默认为true。
- configrable:属性是否可配置。即属性能否通过delete删除,能否修改属性的特性,或者能否把属性修改为访问器属性。是一个bool值,默认为true。
我们最初开始创建的person对象的属性name,它的value为“Nicholas”,其他描述符为true。
访问器属性
访问器属性的描述符的有四个属性分别是:
- get:在读取属性时调用的函数。默认值为 undefined。
- set:在写入属性时调用的函数。默认值为 undefined。
- enumerable:属性是否可枚举,即能否通过for-in循环返回属性。是一个bool值,默认为true。
- configrable:属性是否可配置。即属性能否通过delete删除,能否修改属性的特性,或者能否把属性修改为数据属性。是一个bool值,默认为true。
我们最初开始创建的person对象的属性job,它的get和set值分别是我们指定的函数,其他描述符为true。
要修改属性默认的特性,必须使用 ECMAScript 5 的 Object.defineProperty或 Object.defineProperties。
有了定义属性特性的方法,那我们通过代码来探索下这些属性特性的作用:
1 var person ={}; 2 // 除了configrable之外,其他三个属性相互之间不会影响,读者可以自己测试 3 4 console.log(‘---------------------1 writable start---------------------‘); 5 Object.defineProperty(person, "name", { 6 writable: false, 7 enumerable: true, 8 configurable: true, 9 value: "Nicholas" 10 }); 11 12 console.log("1.1 " + person.name); // "Nicholas" 13 person.name = "Greg"; 14 // writable为false,属性不可修改 15 console.log("1.2 " + person.name); // "Nicholas" 16 17 // writable为false,但configrable为true,我们可以重新配置属性描述符, 18 Object.defineProperty(person, "name", { 19 writable: false, 20 enumerable: true, 21 configurable: true, 22 value: "John" 23 }); 24 console.log("1.3 " + person.name) // John 25 26 delete person.name 27 //但configrable为true,属性可以被删除 28 console.log("1.4 " + person.name) // undefined 29 console.log(‘---------------------1 writable end--------------------- ‘); 30 31 console.log(‘---------------------2 enumerable start---------------------‘); 32 var person = {}; 33 Object.defineProperty(person, "name", { 34 writable: false, 35 enumerable: true, 36 configurable: true, 37 value: "Nicholas" 38 }); 39 // enumerable为true属性可枚举 40 for (var prop in person) { 41 console.log("2.1 " + prop); // name 42 } 43 44 Object.defineProperty(person, "name", { 45 writable: false, 46 enumerable: false, 47 configurable: true, 48 value: "Nicholas" 49 }); 50 // enumerable为false属性不可枚举,循环体不执行 51 for (var prop in person) { 52 console.log("2.2 " + prop) // 53 } 54 console.log(‘---------------------2 enumerable end--------------------- ‘); 55 56 console.log(‘---------------------3 configurable start---------------------‘); 57 var person = {}; 58 Object.defineProperty(person, "name", { 59 writable: true, 60 enumerable: true, 61 configurable: false, 62 value: "Nicholas" 63 }); 64 // configurable为false,writable为true,属性仍然可修改 65 person.name = "John" 66 console.log("3.1 " + person.name); // John 67 68 // configurable为false,writable为true,仍然可以通过配置的方式改变属性值 69 Object.defineProperty(person, "name", { 70 writable: true, 71 enumerable: true, 72 configurable: false, 73 value: "Nicholas" 74 }); 75 console.log("3.2 " + person.name) // Nicholas 76 77 // configurable为false,enumerable为ture,属性可枚举 78 for (var prop in person) { 79 console.log("3.3 " + prop) // name 80 } 81 82 // configurable为false,我们仍然可以把writable属性由true改为false 83 Object.defineProperty(person, "name", { 84 writable: false, 85 enumerable: true, 86 configurable: false, 87 value: "Nicholas" 88 }); 89 console.log("3.4 " + Object.getOwnPropertyDescriptor(person, "name"))//{value: "Nicholas", writable: false, enumerable: true, configurable: false} 90 91 // configurable为false,writable为false,不能通过配置改变value的值 92 try{ 93 Object.defineProperty(person, "name", { 94 writable: false, 95 enumerable: true, 96 configurable: false, 97 value: "John" 98 }); 99 } catch(error) { 100 console.log("3.5 " + "value change error"); 101 console.log(Object.getOwnPropertyDescriptor(person, "name"))//{value: "Nicholas", writable: false, enumerable: true, configurable: false} 102 } 103 104 // configurable为false,但是不能把writable属性由false改为true 105 try{ 106 Object.defineProperty(person, "name", { 107 writable: true, 108 enumerable: true, 109 configurable: false, 110 value: "Nicholas" 111 }); 112 } catch(error) { 113 console.log("3.6 " + "writable false to true error") 114 console.log(Object.getOwnPropertyDescriptor(person, "name"))//{value: "Nicholas", writable: false, enumerable: true, configurable: false} 115 } 116 117 // configurable为false,不能改变enumerable的值 118 try{ 119 Object.defineProperty(person, "name", { 120 writable: false, 121 enumerable: false, 122 configurable: false, 123 value: "Nicholas" 124 }); 125 } catch(error) { 126 console.log("3.7 " + "enumerable change error"); 127 console.log(Object.getOwnPropertyDescriptor(person, "name"))//{value: "Nicholas", writable: false, enumerable: true, configurable: false} 128 } 129 130 var person = {}; 131 Object.defineProperty(person, "name", { 132 writable: true, 133 enumerable: true, 134 configurable: true, 135 value: "Nicholas" 136 }); 137 138 // configurable为true,可以把数据属性修改为访问器属性 139 try{ 140 Object.defineProperty(person, "name", { 141 142 get: function(){return "Nicholas"}, 143 enumerable: true, 144 configurable: false 145 }); 146 } catch(error) { 147 console.log("3.8 " + "get error"); 148 } 149 console.log("3.9 " + Object.getOwnPropertyDescriptor(person, "name"))//{set: undefined, enumerable: true, configurable: false, get: ?} 150 151 var person = {}; 152 Object.defineProperty(person, "name", { 153 writable: true, 154 enumerable: true, 155 configurable: false, 156 value: "Nicholas" 157 }); 158 // configurable为false,不可以把数据属性修改为访问器属性 159 try{ 160 Object.defineProperty(person, "name", { 161 get: function(){return "Nicholas"}, 162 enumerable: true, 163 configurable: false 164 }); 165 } catch(error) { 166 console.log("3.10 " + "get error"); 167 } 168 console.log("3.11 " + Object.getOwnPropertyDescriptor(person, "name"))//{value: "Nicholas", writable: true, enumerable: true, configurable: false} 169 console.log(‘---------------------3 configurable end--------------------- ‘);
输出结果:
1 1.3 John 2 1.4 undefined 3 ---------------------1 writable end--------------------- 4 ---------------------2 enumerable start--------------------- 5 2.1 name 6 ---------------------2 enumerable end--------------------- 7 ---------------------3 configurable start--------------------- 8 3.1 John 9 3.2 Nicholas 10 3.3 name 11 { value: ‘Nicholas‘, 12 writable: false, 13 enumerable: true, 14 configurable: false } 15 3.5 value change error 16 { value: ‘Nicholas‘, 17 writable: false, 18 enumerable: true, 19 configurable: false } 20 3.6 writable false to true error 21 { value: ‘Nicholas‘, 22 writable: false, 23 enumerable: true, 24 configurable: false } 25 3.7 enumerable change error 26 { value: ‘Nicholas‘, 27 writable: false, 28 enumerable: true, 29 configurable: false } 30 3.9 [object Object] 31 3.10 get error 32 3.11 [object Object] 33 ---------------------3 configurable end---------------------
以上是关于Web开发——JavaScript基础(继承)的主要内容,如果未能解决你的问题,请参考以下文章
Python自动化开发学习的第十二周----WEB基础(JavaScript+Dom)
JavaScript之基础-16 JavaScript 原型与继承