扫二维码与项目经理沟通
我们在微信上24小时期待你的声音
解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流
今天遇到关于javascript原型的一道面试题,现分析下:
站在用户的角度思考问题,与客户深入沟通,找到牡丹网站设计与牡丹网站推广的解决方案,凭借多年的经验,让设计与互联网技术结合,创造个性化、用户体验好的作品,建站类型包括:成都做网站、网站设计、企业官网、英文网站、手机端网站、网站推广、国际域名空间、虚拟主机、企业邮箱。业务覆盖牡丹地区。
原题如下:
function
A(){
}
function
B(a){
this.a
=
a;
}
function
C(a){
if(a){
this.a
=
a;
}
}
A.prototype.a
=
1;
B.prototype.a
=
1;
C.prototype.a
=
1;
console.log(new
A().a);
console.log(new
B().a);
console.log(new
C(2).a);
分析:
console.log(new
A().a);//new
A()为构造函数创建的对象,本身没有a属性,所以向它的原型去找,发现原型的a属性的属性值为1,故该输出值为1;
console.log(new
B().a);//new
B()为构造函数创建的对象,该构造函数有参数a,但该对象没有传参,故该输出值为undefined;
console.log(new
C(2).a);//new
C()为构造函数创建的对象,该构造函数有参数a,且传的实参为2,执行函数内部,发现if为真,执行this.a
=
2,故属性a的值为2;
故这三个的输出值分别为:1、undefined、2.
以上就是小编为大家带来的关于js原型的面试题讲解的全部内容了,希望对大家有所帮助,多多支持脚本之家~
首先我们来定义LockingPtr用到的Mutex类的骨架:
class Mutex
{
public:
void Acquire();
void Release();
...
};
为了能使用LockingPtr,你要用你操作系统用到的数据结构和基本函数来实现Mutex。
LockingPtr用受控的变量的类型来作为模板。举例来说,如果你想管理一个Widget,你使用一个LockingPtrWidget,这样你可以用一个类型为volatile Widget的变量来初始化它。
LockingPtr的定义非常简单。LockingPtr实现一个相对简单的smart pointer。它目的只是把一个const_cast和一个临界区集中在一起。
Template typename T
Class LockingPtr {
Public:
//构造/析构函数
LockingPtr(volatile T obj, Mutex mtx)
: pObj_(const_castT*(obj)),
pMtx_(mtx)
{ mtx.Lock(); }
~LockingPtr()
{ pMtx_-Unlock(); }
//模拟指针行为
T operator*()
{ return *pObj_; }
T* operator-()
{ return pObj_; }
private:
T* pObj_;
Mutex* pMtx_;
LockingPtr(const LockingPtr);
LockingPtr operator=(const LockingPtr);
};
尽管简单,LockingPtr对写出正确的多线程代码非常有帮助。你应该把被几个线程共享的对象定义为volatile而且不能对它们使用const_cast——应该始终使用LockingPtr自动对象。我们通过一个例子来说明:
假设你有两个线程共享一个vectorchar对象
class SyncBuf {
public:
void Thread1();
void Thread2();
private:
typedef vectorchar BufT;
volatile BufT buffer_;
Mutex mtx_; //控制对buffer_的访问
}; 软件开发网
在一个线程函数中,你简单地使用一个LockingPtrBufT来取得对buffer_成员变量的受控访问:
void SyncBuf::Thread1() {
LockingPtrBufT lpBuf(buffer_, mtx_);
BufT::iterator I = lpBuf-begin();
For (; I != lpBuf-end(); I) {
...使用*i...
}
}
这些代码既非常容易写也非常容易懂——任何时候你需要用到buffer_,你必须创建一个LockingPtrBufT指向它。一旦你这样做,你就能够使用vecotr的所有接口。
非常好的事情是,如果你犯了错,编译器会指出来:
void SyncBuf::Thread2() {
//错误,不能对一个volatile对象调用begin()
BufT::iterator I = buffer_.begin();
//错误!不能对一个volatile对象调用end()
for (; I != lpBuf-end(); I) {
...使用*i...
}
}
你不能调用buffer_的任何函数,除非你要么使用一个const_cast要么使用LockingPtr。区别是LockingPtr提供了一个有序的途径来对volatile变量使用const_cast。
LockingPtr非常有表现力。如果你只需要调用一个函数,你能够创建一个无名临时LockingPtr对象并直接使用它:
Unsigned int SyncBuf::Size() {
Return LockingPtrBufT(buffer_, mtx_)-size();
}
回到基本类型
我们已经看到了volatile保护对象不被不受控制地访问时是多么出色,也看到了LockingPtr提供了多么简单和高效的方法来写线程安全的代码。让我们回到基本类型,那些加了volatile后行为与用户自定类型不同的类型
我们来考虑一个例子,多个线程共享一个类型为int的变量。
Class Count
{
public:
...
void Increment() { ctr_; }
void Decrement() { --ctr_; }
private:
int ctr_;
};
如果Increment和Decrement被不同线程调用,上面的代码片段是有问题的。首先,ctr_必须是volatile,其次,即使象 ctr_那样看上去是原子操作的函数实际上是一个三步操作。内存本身没有算术能力,当递增一个变量时,处理器:
* 读取那个变量到寄存器
* 在寄存器中增加值
* 把结果写回内存
这个三步操作叫做RMW(Read-ModifyWrite 读-改-写)。在执行一个RMW操作的“改”
操作时,为了让其他处理器访问内存,大多数处理器会释放内存总线。
如果那时另一个处理器对同一个变量执行一个RMW操作,我们就有了一个竟态条件;第二个写操作覆盖了第一个的结果。
你也能够用LockingPtr避免这种情况:
class Counter
{
public:
...
void Increment() { *LockingPtrint(ctr_, mtx_); }
void Decrement() { --*LockingPtrint(ctr_, mtx_); }
private:
volatile int ctr_;
Mutex mtx_;
};
现在代码正确了,但代码质量比较SyncBuf的代码而言差了很多。为什么?因为在Counter里,如果你错误地直接访问ctr_(没有先对它加锁)编译器不会警告你。如果ctr_是volatile, ctr_也能编译通过,但产生的代码明显是错误的。编译器不再是你的帮手了,只有靠你自己注意才能避免这样的竟态条件。
那你应该怎么做?简单地把你用到的基本数据包装为更高层次的结构,对那些结构用volatile。荒谬的是,尽管本来volatile的用途是用在内建类型上,但实际上直接这样做不是个好主意!
volatile成员函数
到目前为止,我们已经有了包含有volatile数据成员的类,现在我们来考虑设计作为更大对象一部分的类,这些类也被多线程共享。在这里用volatile成员函数有很大帮助。
当设计你的类时,你只对那些线程安全的成员函数加voaltile标识。你必须假定外部代码会用任何代码在任何时刻调用volatile函数。不要忘记:volatile等于可自由用于多线程代码而不用临界区,非volatile等于单线程环境或在一个临界区内。
例如,你定义一个Widget类,实现一个函数的两个变化——一个线程安全的和一个快的,无保护的。
Class Widget
{
public:
void Operation() volatile;
void Operation();
...
private:
Mutex mtx_;
};
注意用了重载。现在Widget的用户可以用同样的语法来调用Operation,无论你为了获得线程安全调用volatile对象的Operation还是为了获得速度调用常规对象的Operation。但用户必须小心地把被多线程共享的Widget对象定义为volatile。
当实现一个volatile成员函数时,第一个操作通常是对this用一个LockingPtr加锁。剩下的工作可以交给非volatile的对应函数:
软件开发网
void Widget::Operation() volatile
{
LockingPtrWidget lpThis(*this, mtx_);
LpThis-Operation(); //调用非volatile函数
}
总结
当写多线程程序时,你可以用volatile得到好处。你必须遵守下面的规则:
* 定义所有的被共享的对象为volatile。
* 不要对基本类型直接用volatile
* 当定义可被共享类时,使用volatile成员函数来表示线程安全。
如果你这样做,而且如果你使用那个简单的返型组件LockingPtr,你能够写出线程安
全的代码而不用更多考虑竟态条件,因为编译器能为你留心,会为你主动指出你错误的地方。
我参与的几个使用volatile和LockingPtr的计划获得很好的效果。代码清晰易懂。我记得碰到几处死锁,但我情愿遇到死锁也不要竟态条件,因为死锁调试起来容易得多。事实上没有遇到任何问题是关于竟态条件的。
第一本:《JavaScript权威指南》,经典级教材,很厚一本,俗称“犀牛书”,囊括了JS几乎所有的基础知识,新版本还加入了最新的技术内容,适合初学者,有经验的开发者也常常作为随手翻阅的语法书。
第二本:《JavaScript语言精粹》,俗称“蝴蝶书”,是介绍JavaScript语言本质一本书,教你全面了解这门语言的糟粕部分,构建出优雅高效的代码。
第三本:《JavaScript高级程序设计》,这本是我强烈推荐的,是非常经典的JavaScript畅销书,内容全面深入、贴近实战,详细讲解了JavaScript语言的核心,又展示了现有规范及实现以及为开发Web应用提供的各种支持和特性。
srcElement 是Dom事件中的事件最初指派到的元素。
比如有一个div,里面有一个按钮。你响应div的onclick事件,但实际上,你单击的只是它内部的按钮,那么,srcElement指向的,就是那个按钮。
srcElement只在IE中有效。
在Opera系列浏览器中对应的属性是target
给你一个IE下使用的例子。
!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" ""
html xmlns=""
head
title无标题页/title
script type="text/javascript"
function onLoad()
{
document.getElementById( "myDiv" ).attachEvent( "onclick", on_myDivClick );
}
function onUnLoad()
{
document.getElementById( "myDiv" ).detachEvent( "onclick", on_myDivClick );
}
function on_myDivClick( e )
{
if( !e ) e = window.event;
alert( "event: " + e.type + ", fromElement = " + e.srcElement.id );
}
/script
/head
body onload="onLoad()" onunload="onUnLoad()"
div id="myDiv"
input type="button" id="btn1" value="button1" /
input type="button" id="btn2" value="button2" /
/div
/body
/html
学习javascript没HTMl基础有点难度,建议你先熟悉html再学习。
JavaScript简称JS,之前的基础就是HTML,HTML这门课程如果入门的话不是很难,刻苦点一月到两月就能搞定,有HTML基础的话,只要继续刻苦一个月左右JS就能入门,但是想学到高深那就不容易了,js入门后在继续学可以说也是有些难度的。总之先掌握HTML,这是一个基础,正如你说话要先从aoe开始一样,HTML也很容易学的
HTML推荐书籍:深入浅出HTML和CSS
JS推荐书籍:《javascript入门经典》
这些书籍可以帮助你怎么学习,其实不止看书,你也可以看看视频,多看视频讲解学习可以让你少走很多弯路,节省不少时间。遇见问题,常百度一下,现在百度只有你想不到的,没有你查不到的,没有你要的答案,也能查到相关的,何况可以提问嘛……
人就是在不断的问题中解决问题,发现新的问题,继续解决问题,这样自己的自学能力和技术能够得到很大的提升,关键就是不懂一定马上问,千万不要随便拖,这样进步才叫快……
还有补充一下,学习重在实践,因为只有实践你才能更好的发现自己的问题,一个问题解决了,一次不记得,下次继续做的时候再手打一次,但是别抄之前自己写过的代码,除非你觉得自己这段代码已经掌握了,这样为了节省时间才抄,否则还是练练手最好,,万变不离其宗——熟能生巧……
如果你精通了,那就好办了,一个网站可能就被你开发出来,然后就不愁找不到好工作了,至于你认为学到什么地步算精通,这你自己在学习中就可以感受到自己的能力,说的够多了,一时说不完,就这样,最后祝你成功,嘎嘎嘎嘎……
我们在微信上24小时期待你的声音
解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流