怎样在小程序里实现标题的更改
880
2022-11-10
js中的原型
一:原型属性
函数本身也是一个包含了方法和属性的对象。
定义一个函数foo(),访问其他对象一样访问该函数的属性:
function foo(a, b) { return a * b;}foo.length--2
foo.constructorƒ Function() { [native code] }
函数定义时被创建的属性就包括有prototype属性,他的初始值是一个“空”对象
typeof foo.prototype"object"
可以自己添加该属性
foo.prototype={};
1.利用原型添加方法和属性
构建一个具体的构造函数Gadget(),在新建时为其添加属性和方法。
function Gadget(name, color) { this.name = name; this.color = color; this.whatAreYou = function () { return 'I am a ' + this.color + '' + this.name; };}
通过构造器函数的prototype属性来增加该构造器所能提供的功能
Gadget.prototype.price = 100;Gadget.prototype.rating = 3;Gadget.prototype.getInfo = function () { return 'Rating:' + this.rating + ',price: ' + this.price;}
也可以另外定义一个对象,将其覆盖到之前的原型上:
Gadget.prototype = { price: 100, rating: }
2.使用原型的方法和属性:
直接用该构造器来新建对象,就可以访问之前定义的那些属性和方法。
var newtoy=new Gadget('webcam','black');
newtoy.name;"webcam"
newtoy.color;"black"
newtoy.whatAreYou();"I am a blackwebcam"
newtoy.price;100
newtoy.rating;3
newtoy.getInfo();"Rating:3,price: 100"
可以随时修改prototype属性,并且由同一构造器创建的所有对象的prototype属性也同时改变。
向原型中添加一个新方法:
Gadget.prototype.get = function (what) { return this[what];};
newtoy对象在get()方法定义之前就已经被创建,我们依然可以在该对象中访问新增的方法:
newtoy.get('color');"black"newtoy.get('price');100
3.自身属性与原型属性
在getInfo()的示例中,我们使用this指针来完成对象的访问,但其实直接引用Gadget.prototype也可以完成同样的操作:
Gadget.prototype.getInfo = function () { return 'Rating: ' + Gadget.prototype.rating + ',price: ' + Gadget.prototype.price;};
回到之前的那个newtoy对象上:
var newtoy = new Gadget('webcam', 'black');
newtoy.name"webcam"
newtoy.rating3
每个对象都有属于自己的构造器属性,所引用的就是用于创建该对象的那个函数
newtoy.constructor===Gadgettrue
newtoy.constructor.prototype.rating;3
每个对象都会有一个构造器,而原型本身也是一个对象,这意味着它也必然有一个构造器,而这个构造器又会有自己的原型,这种结构可能会一直不断的持续下去,并最终取决于原型链的长度,但最后一环肯定是Object内建对象,它是最高级的父级对象。
4.利用自身属性重写原型属性
如果一个对象自身属性中没有找到指定的属性,就会使用原型链中查找到的相关属性,如果,对象的自身属性与原型属性同名,自身属性的优先级高于原型属性。
示例:同一个属性名同时出现在对象的自身属性和原型属性中:
function Gadget(name) { this.name = name;}Gadget.prototype.name = 'sunyajing';
新建一个对象,并访问该对象自身的name属性
var toy = new Gadget('camera'); toy.name;"camera"
通过hasOwnProperty()判断一个属性是自身属性还是原型属性
toy.hasOwnProperty('name');true
删除这个属性,同名的原型属性就会“浮出水面”
delete toy.name; true
toy.name;"sunyajing"
toy.hasOwnProperty('name');false
我们随时可以重建这个对象的自身属性:
toy.name = 'camera'; toy.name;"camera"
判读一个对象的某个原型属性到底是原型链中哪个原型的属性呢?可以用hasOwnProperty()属性:
toy.toString();"[object Object]"
toy.hasOwnProperty('toString');false
toy.constructor.hasOwnProperty('toString');false
toy.constructor.prototype.hasOwnProperty('toString');false
Object.hasOwnProperty('toString');false
Object.prototype.hasOwnProperty('toString');true
for 更适合数组,for-in更适合对象,构造URL字符串为例:
var params = { productid: 666, section: 'products' }; var url = ' i, query = []; for (i in params) { query.push(i + '=' + params[i]); } url += query.join('&');"Gadget(name, color) { this.name = name; this.color = color; this.getName = function () { return this.name; }; } Gadget.prototype.price = 100; Gadget.prototype.rathing = 3;
对他执行for-in循环,就会列出该对象中的所有属性,包括原型中的属性:
for (var prop in newtoy) { console.log(prop + ' = ' + newtoy[prop]); }
结果:
name = webcam color = black getName = function () { return this.name; } price = 100 rathing = 3
如果要对对象属性和原型属性做一个区分,就要调用hasOwnProperty()方法:
newtoy.hasOwnProperty('name');truenewtoy.hasOwnProperty('price');false
显示对象的自身属性:
for (var prop in newtoy) { if (newtoy.hasOwnProperty(prop)) { console.log(prop + ' = ' + newtoy[prop]); } }
结果:
name = webcam color = black getName = function () { return this.name; }
propertyIsEnumerable()会对所有的非内建对象属性返回true
newtoy.propertyIsEnumerable('name');true
对于内建属性和方法大部分是不可枚举的
newtoy.propertyIsEnumerable('constructor');false
如果propertyIsEnumerable()的调用是来自原型链上的某个对象,那么该对象中的属性是可枚举的
newtoy.constructor.prototype.propertyIsEnumerable('price');true
5.isPrototypeOf()方法
每个对象中都会有一个isPrototypeOf()方法,这个方法告诉我们当前对象是否是另一个对象的原型
var monkey = { hair: true, feeds: 'bananas', breathes: 'air' };
创建一个Human的构造器函数,并设置原型属性指向monkey:
Human.prototype = monkey;
Human.prototype = monkey; var george = new Human('George'); monkey.isPrototypeOf(george);
不知道某个原型的情况下,获得对象的原型。
Object.getPrototypeOf(george).feeds; Object.getPrototypeOf(george) === monkey;
6.神秘的_proto_链接
改写用monkey对象做原型的Human()对象构造器。
var monkey = { feeds: 'bananas', breathes: 'air' }; function Human() { } Human.prototype = monkey;
创建一个developer对象,并赋予它一些属性:
var developer = new Human(); developer.feeds = 'pizza'; developer.hacks = 'JavaScript';
访问:
developer.hacks; -- "JavaScript" developer.feeds; -- "pizza"
但是breathes在developer对象自身的属性中是不存在的,所以就得去原型中查找
developer.breathes;"air"
这个神秘的链接叫做__proto__属性
developer.__proto__ === monkey;true
__proto__是某个实例对象的属性,而prototype则是属于构造器函数的属性。
typeof developer.__proto__"object"
typeof developer.prototype;"undefined"
typeof developer.constructor.prototype;"object"
二:扩展内建对象
内建对象的构造器函数(Array、String、Object、Function)都是可以通过原型来扩展的
Array.prototype.inArray = function (needle) { for (var i = 0, len = this.length; i < len; i++) { if (this[i] === needle) { return true; } } return false; }; var colors = ['red', 'green', 'blue']; colors.inArray('red');true
colors.inArray('yellow');false
反转字符串的功能:
String.prototype.reverse = function () { return Array.prototype.reverse.apply(this.split('')).join(''); }
"sunyujing".reverse();"gnijuynus"
为String对象添加trim()方法
if(typeof String.prototype.trim !== 'function'){ String.prototype.trim = function(){ return this.replace(/^\s+|\s+&/g,''); }; } " hwllow ".trim();"hwllow"
如果想要通过原型为某个对象添加一个新属性,务必检查一下该属性是否已经存在
三:原型陷阱
处理原型时,特别注意以下两种行为:
1.我们对原型对象执行完全替换时,可能会触发原型链中某种异常(exception)
2.prototype.constructor属性不可靠
新建一个简答的构造器函数,并创建两个对象
function Dog() { this.tail = true; } var benji = new Dog(); var rusty = new Dog();
添加一个Say()方法:
Dog.prototype.say = function () { return 'Woof'; };
上面的两个对象都可以访问该新方法。
benji.say();"Woof"
rusty.say();"Woof"
检查一下这些对象构造器函数,会发现一切正常。
benji.constructor === Dog;--truerusty.constructor === Dog;--true
用一个自定义的新对象完全覆盖掉原有的原型对象:
Dog.prototype = { paws: 4, hair: true };
这会使原有对象不能访问原型的新增属性,依然通过那个神秘的链接与原有的原型对象保持联系。
typeof benji.paws;--"undefined"
benji.say();--"Woof"
typeof benji.__proto__.say; --"function"
typeof benji.__proto__paws;--"undefined"
之后创建的所有对象使用的都是被更新后的prototype对象
var lucy = new Dog(); lucy.say();Uncaught TypeError: lucy.say is not a function
lucy.paws;--4
其神秘的链接__proto__也指向了新的prototype对象
typeof lucy.__proto__.paws; ---"number" typeof lucy.__proto__.say; ---"undefined"
新对象的constructor属性就不能再保持正确了,原本是Dog()的引用却指向了Object()
lucy.constructor;--ƒ Object() { [native code] }
benji.constructor;--ƒ Dog() { this.tail = true; }
也可以通过重新设置constructor属性来解决上述所有的异常行为:
function Dog() { } Dog.prototype = {}; new dog().constructor === Dog;--false
Dog.prototype.constructor = Dog; new Dog().constructor === Dog;true
当我们重写某个对象的prototype时,需要重新设置相应的constructor属性。
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。
发表评论
暂时没有评论,来抢沙发吧~