倔强,倔的正确读音是什么?
jué第二声,
“倔”,普通话读音为jué、juè,初见于传抄古文。在读jué时,“倔”的基本含义为顽强,固执,如倔强(jiàng);引申含义为“倔”古同“崛”,突出。在读juè时,“倔”的含义为言语粗直,态度不好,如那老头真倔。
在日常使用中,“倔”也常做形容词,表示奇谲,如倔傀、倔佹。
半条命怎么换第三人称模式?
控制台中输入sv_cheats1然后保存、读取再次输入thirdperson就OK但这种模式效果极差我相信你还会再输入一次firstperson的
如何理解Javascript的原型和原型链?
Javascript中的原型和原型链都是实现OOP的手段,OOP在Javascript中的具体实现如下:
对象(Object)就是属性(Property)的集合,特别的,称值(Value)为函数(Function)的属性为方法(Method)。将相似对象的共有属性提取出来聚集在一起就形成了类(Class),这些对象称为该类的实例(Instance)。同样,将相似类的共有属性提取出来聚集在一起也形成新的类,这个类是前面那些类的超类(SuperClass),前面那些类是这个类的子类(SubClass)。多个超类还可以作为子类聚集出一个新的超类,这个过程会一持续下去,直到出现名为Object的类,它的超类为空(Null)。
类除了是共有属性的聚集外,还担负对象工厂(ObjectFactory)的职责。一个类的实例对象由类的构造函数(Constructor)负责创建。构造函数负责两件事:
创建对象;
初始化该对象;
因为前者的实现已经由方法提供,所以构造函数真正需要完成的就是初始化对象,这里又分为两件事情:
让对象具有类所聚集的共有属性;
根据参数,对某些对象的属性进行特化;
对于第二件事情,没什么说的,就是将特化的属性添加到待初始化的对象中去。对于第一件事,也可以仿照后者的实现方法,但是这不是一个明智的选择,因为这些共有属性的值在大多数情况下是不会发生改变的。Javascript选择的方法是:
以这些共有属性为属性并赋予默认属性值,创建一个原型(Prototype)对象;
初始化时,将原型对象赋予待初始化对象的特殊属性:__proto__;
也就是说,一个类对应一个原型对象,在初始化时,用__proto___将实例对象和原型对象连接起来。
特殊属性__proto__不仅负责连接实例和原型,还负责连接子类和超类的原型对象,以实现类之间的继承关系。这样以来,一个对象的类原型,超类原型,超类的超类原型,...就由__proto__连接成一个“链”,称为该对象的原型链。允许,一个对象的__proto__属性为null,这表明该对象没有原型链,Object类的原型就是这样的。
为了让原型初始化实例的方法真正得以实现,必须在对象的属性访问上进行配合:
读取属性值:先在对象中查找该属性,如果存在则返回其值,否则,在原型对象中查找,如果存在则返回其值,否则,在原型对象的原型对象中查找,...,直到原型链为null,表示该属性未定义,返回undefined;
给属性赋值:在对象中查找该属性,如果存在则对其赋值,如果不存在则在对象中创建该属性然后对其赋值;
删除属性:如果该属性在对象中存在则删除它,否则什么都不做。
这套访问机制保证了:对象属性可以覆盖(去覆盖)原型属性,但是不会改变原型属性,这就是OOP的多态性。
构造函数在创建对象时需要用到原型对象,它是通过prototype属性知道其对应类的原型对象的。另外,为让实例对象知道是谁创建了它,它的constructor属性会“抓着”构造函数。类的原型对象也被认为是该类的构造函数构创建的。
接下来我们看一下实现OOP的具体代码:
首先,不考虑继承关系,声明一个类的范例代码如下:
注:特殊属性__proto__是undocumented应该避免直接使用,正式的做法是调用方法,它的参数就是所要创建对象的原型对象。注:遵照OOP语言的传统,构造函数的名字就是类的名字。
当一个函数被调用时,如果this上下文(Context)绑定的是一个普通对象(而非null或全局对象window),则这个函数就是作为该对象的方法被调用。
当我们用new表达式创建对象时,构造函数就是以方法的被new调用:
上面范例代码中构造函数开始和结束部分所作的事情,new表达式,就替我们干了:
new会创建一个空白对象,让其,原型链绑定构造函数的prototype属性,让其,constructor属性绑定构造函数;然后以该对象为this上下文调用构造函数,如果构造函数没有返回值,则以空白对象作为创建的对象。写成代码就是:
被new调用的构造函数,已经转变为构造方法,但为了让其还保留构造函数的能力,一般这样实现:
接下来,考虑类的继承。
一个实例对象的初始化过程是:先被超类的构造函数初始化,之后才被子类的构造函数初始化,这样才能达到子类覆盖超类的要求。基于此,范例代码如下:
写到这里,我们发现又是一堆不得不写的规范代码。于是早期很多前端框架,都纷纷的提供了以上代码的封装方案,旦各自为政,没有统一的解决方法,直到ES6直接提供了class语法,整个事情才算告一段落:
注:Javascript中的属性分为存储属性和访问属性(分别对应传统OOP语言中的字段(Field)和属性),class中只能声明原型中方法和访问属性,而在原型中声明存储属性还得是老办法。
class表达式只是语法层面的封装,最终依然是基于原型和原型链这套实现。
虽然我们现在已经不需要按照那套复杂的规范声明类了,但是了解原型和原型链对应深入理解Javascript的OOP机制依然十分重要。
最后,给出Javascript内建对象之间的原型链关系图(粗箭头是__proto__属性,细箭头是prototype属性,虚箭头是constructor属性):
(Value:Number,String,Boolean;Symbol,Container:Array,Set,Map)