1.ECMAScript和javaScript的关系
可简单概括为:ECMAScript是JavaScript的规范,JavaScript是ECMAScript的实现。
红宝书第一章小结:
js是一种专为与网页交互而设计的脚本语言,由下列三个不同部分组成:
核心ECMAScript,提供核心语言功能;
文档对象模型(DOM),提供访问和操作网页内容的方法和接口;
浏览器对象模型(BOM),提供与浏览器交互的方法和接口。
JavaScript实现了ECMAScript规范(同样实现ECMAScript的还有Adobe ActionScript)。JavaScript包括了核心ECMAScript,所以也可以理解为ECMAScript是JavaScript的一部分。
背景故事:1996年11月,JavaScript的创造者—Netscape公司,将JavaScript提交给欧洲计算机制造商协会(ECMA,European Computer Manufacturers Association),希望这门语言能够成为国际标准。次年,ECMA发布262号标准文件(ECMA-262)的第一版,规定了浏览器脚本语言的标准,并将这种语言称为 ECMAScript,这个版本就是1.0版。
该标准从一开始就是针对 JavaScript 语言制定的,但是之所以不叫 JavaScript,有两个原因。一是商标,Java 是 Sun 公司的商标,根据授权协议,只有 Netscape 公司可以合法地使用 JavaScript 这个名字,且 JavaScript 本身也已经被 Netscape 公司注册为商标。二是想体现这门语言的制定者是 ECMA,不是 Netscape,这样有利于保证这门语言的开放性和中立性。
因此,ECMAScript 和 JavaScript 的关系是,前者是后者的规格,后者是前者的一种实现(另外的 ECMAScript 方言还有 Jscript 和 ActionScript)。日常场合,这两个词是可以互换的。
2.给网页添加javascript的方式有几种?
1.使用script标签,将javascript代码写到之间
js使用方式2:内部js
2.添加外部javascript文件
js使用方式3:外部js
3.使用行内javascript
js使用方式1:行内js
3.JavaScript语言特性
javascript 语言特性中,有很多方面和我们接触的其他编程语言不太一样,比如说,javascript语言实现继承机制的核心就是 ___,而不是Java语言那样的类式继承。
Javascript 解析引擎在读取一个Object的属性的值时,会沿着 ___向上寻找,如果最终没有找到,则该属性值为 ___; 如果最终找到该属性的值,则返回结果。
与这个过程不同的是,当javascript解析引擎执行“给一个Object的某个属性赋值”的时候,如果当前Object存在该属性,则改写该属性的值,如果当前的Object本身并不存在该属性,则赋值该属性的值 。
- prototype机制(或原型机制)
- 原型链
- undefined
4.什么是JavaScript原型、原型链?有什么特点?
1.什么是原型,原型有什么特点:
JavaScript 的每个对象都继承另一个对象,后者称为“原型”(prototype)对象。只有null除外,它没有自己的原型对象。
使用原型的好处是:原型对象上的所有属性和方法,都能被对应的构造函数创建的实例对象共享(这就是 JavaScript 继承机制的基本设计),也就是说,不必在构造函数中定义对象实例的信息,而是可以将这些信息直接添加到原型对象中。
每一个构造函数都有一个prototype(原型)属性,这个属性就是使用构造函数创建出来的实例对象的原型对象。
2.什么是原型链,原型链有什么特点
对象的属性和方法,有可能是定义在自身,也有可能是定义在它的原型对象上。由于原型本身也是对象,又有自己的原型,所以形成了一条原型链(prototype chain)。
如果一层层地上溯,所有对象的原型最终都可以上溯到Object.prototype,即Object构造函数的prototype属性指向的那个对象。而Object.prototype对象的原型就是没有任何属性和方法的null对象,而null对象没有自己的原型。
“原型链”的作用是,读取对象的某个属性时,JavaScript 引擎先寻找对象本身的属性,如果找不到,就到它的原型去找,如果还是找不到,就到原型的原型去找。如果直到最顶层的Object.prototype还是找不到,则返回undefined。
如果对象自身和它的原型,都定义了一个同名属性,那么优先读取对象自身的属性,这叫做“覆盖”(overriding)。
需要注意的是,一级级向上,在原型链寻找某个属性,对性能是有影响的。所寻找的属性在越上层的原型对象,对性能的影响越大。如果寻找某个不存在的属性,将会遍历整个原型链。
5.解释一下JavaScript的同源策略
1.什么是同源?
所谓“同源”指的是”三个相同“。相同的域名、端口和协议,这三个相同的话就视为同一个域,本域下的JS脚本只能读写本域下的数据资源,无法访问其它域的资源。
协议相同
域名相同
端口相同(如果没有写端口,默认是80端口)
2.什么是同源策略?
同源策略是浏览器为了保护用户的个人信息以及企业数据的安全而设置的一种策略,不同源的客户端脚本是不能在对方未允许的情况下访问或索取对方的数据信息;
3.同源策略的目的
同源政策的目的,是为了保证用户信息的安全,防止恶意的网站窃取数据。
设想这样一种情况:A 网站是一家银行,用户登录以后,又去浏览其他网站。如果其他网站可以读取 A 网站的 Cookie,会发生什么?
很显然,如果 Cookie 包含隐私(比如存款总额),这些信息就会泄漏。更可怕的是,Cookie 往往用来保存用户的登录状态,如果用户没有退出登录,其他网站就可以冒充用户,为所欲为。因为浏览器同时还规定,提交表单不受同源政策的限制。
由此可见,“同源政策”是必需的,否则 Cookie 可以共享,互联网就毫无安全可言了。
6.javascript实现继承有几 种方法
1.原型链继承
function Father() {
this.faproperty = true;
}
Father.prototype.getFaValue = function() {
return this.faproperty;
};
function Child() {
this.chproperty = false;
}
//继承了Father
Child.prototype = new Father();
//添加新方法
Child.prototype.getChValue = function() {
return this.chproperty;
};
var instance = new Child();
alert(instance.getFaValue()); //true
使用原型链继承需要注意的地方:
- 子类型有时候需要覆盖父类型中的某个方法,或者需要添加父类型中不存在的某个方法。但不管怎样,给子类型添加方法的代码一定要放在替换原型的语句之后。
原型链继承的问题:
重写子类的原型等于父类的一个实例,那么父类的实例属性变成子类的原型属性,如果父类包含引用类型的属性,那么子类所有实例都会共享该属性 。
在创建子类实例时,不能向父类的构造函数传递参数。实际上,应该说是没有办法在不影响所有对象实例的情况下,给父类的构造函数传递参数。
2.借用构造函数
借用构造函数解决了原型中包含引用类型值所带来的问题。这种技术的基本思想:在子类型构造函数的内部调用超类型构造函数,因为函数只不过是在特定环境中执行代码的对象,因此通过使用apply()和call()方法也可以在新(将来)创建的对象上执行构造函数。
function Father(){
this.colors = ["red","blue","green"];
}
function Child(){
//继承了Father
Father.call(this);
}
var instance1 = new Child();
instance1.colors.push("black");
alert(instance1.colors); //"red,blue,green,black"
var instance2 = new Child();
alert(instance2.colors); //"red,blue,green"
function Child(){ Father.call(this); }
,函数中的Father.call(this);
这行代码,通过使用call()
方法,会在以后将要创建的Child
实例的环境下调用了Father
构造函数。这样一来,就会在新Child
对象上执行Father
构造函数中定义的所有对象初始化代码。结果,Child
的每个实例就都会具有自己的colors
属性的副本了。
借用构造函数的优点:
- 相对于原型链继承而言,借用构造函数有一个很的优势,即可以在子类型构造函数中向父类型构造函数传递参数。
function Father(name){
this.name = name;
}
function Child(){
//继承了Father,同时还传递了参数
Father.call(this,"junjun");
//实例属性
this.age = 24;
}
var instance = new Child();
alert(instance.name); //"junjun"
alert(instance.age); //24
借用构造函数的问题:
- 无法避免构造函数模式存在的问题——方法都在构造函数中定义,因此函数复用就无从谈起。而且,在父类型的原型中定义的方法,对子类型而言也是不可见的,结果所有类型都只能使用构造函数模式。
(。。。。。。。。。来日补充)
7.有几种方法确定原型与实例的关系
1.instanceof操作符,只要用这个操作符来测试实例与原型链中出现过的构造函数,结果就会返回true
alert(instance instanceof Object); //true
alert(instance instanceof SuperType); //true
alert(instance instanceof SubType); //true
//代码例子高程P165
2.isPrototypeOf()方法,只要是原型链中出现过的原型,都可以说是该原型链所派生的实例的原型,结果就会返回true
alert(Object.prototype.isPrototypeOf(instance)); //true
alert(SuperType.prototype.isPrototypeOf(instance)); //true
alert(SubType.prototype.isPrototypeOf(instance)); //true
//代码例子高程P165
3.Object.getPrototypeOf()方法,这个方法返回[[prototype]]的值,使用Object.getPrototypeOf()方法可以方便的取到一个对象的原型
alert(Object.getPrototypeOf(person1) == Person.prototype); //true
alert(Object.getPrototypeOf(person1).name); //"Nicholas"
//代码例子高程P149
8.javascript对象的几种创建方式
- new操作符后跟Object构造函数
var person = new Object();
person.name = "junjun";
person.age = 18;
- 使用对象字面量表示法
var person = {
name: "junjun";
age: 18;
}
- Object.create()方法,使用指定的原型对象及其属性去创建一个新的对象。
function Car (desc) {
this.desc = desc;
this.color = "red";
}
Car.prototype = {
getInfo: function() {
return 'A ' + this.color + ' ' + this.desc + '.';
}
};
var car = Object.create(Car.prototype);
car.color = "blue";
alert(car.getInfo()); //A blue undefined.
9.javascript定义函数的几种方式
1.函数声明
function sum(num1,num2){
return num1+num2;
}
2.函数表达式
var sum = function(num1,num2){
return num1+num2;
}
3.Function构造函数
var sum = new Function("num1","num2","return num1+num2");
10.简要描述Javascript对象层次结构
参考链接
11.使用JavaScript深度克隆一个对象
方法一:
var obj = {
a: 10,
b: 20,
omg: {
name: 'xuguojun',
sex: 'male'
}
}
function deepcopy(obj){
var newobj = {};
for(arr in obj){
if (typeof obj[arr]==='object' && obj[arr] !== null) {
newobj[arr] = deepcopy(obj[arr]); //递归,核心代码
} else {
newobj[arr] = obj[arr];
}
}
return newobj;
}
obj2 = deepcopy(obj);
console.log(obj2); //{a: 10, b: 20, omg: {…}}
obj2.omg.name = 'PDD';
console.log(obj2.omg.name); //"PDD"
console.log(obj.omg.name); //"xuguojun"
方法二:
var obj = {
a: 10,
b: 20,
omg: {
name: 'xuguojun',
sex: 'male'
}
}
function copy(obj){
var newObj = JSON.parse(JSON.stringify(obj));
return newObj;
}
obj2= copy(obj);
console.log(obj2); //{a: 10, b: 20, omg: {…}}
obj2.omg.name = 'PDD';
console.log(obj2.omg.name); //"PDD"
console.log(obj.omg.name); //"xuguojun"
12.请编写一个JavaScript函数,实现清除数据中重复的元素
function del(arr) {
for(var i=0;i
13.Javascript的基础数据类型
最新的 ECMAScript 标准定义了 7 种数据类型:6种原始类型(也称基本数据类型)和1种复杂数据类型。
6种原始类型(也称基本数据类型):
Number:整数和浮点数值(所谓浮点数值,就是该数值中必须包含一个小数点,并且小数点后面必须至少有一位数字)。
String:String类型用于表示由零或多个16位Unicode字符组成的字符序列,即字符串。字符串可以由双引号或单引号表示。
Boolean:Boolean类型只有两个字面值:true和false。
Undefined:Undefined类型只有一个值,即特殊的undefined。在使用var声明变量但未对其初值化时,这个变量的值就是undefined。对未声明的变量执行typeof操作符同样也会返回undefined值。
Null:Null类型是第二个只有一个值的数据类型,这个特殊的值
是null。null值表示通常有意地指向不存在或无效的对象或地址的引用,从逻辑角度看,null值表示一个空对象指针,而这也正是使用typeof操作符检测null值时会返回“object”的原因。如果定义的变量准备在将来用于保存对象,那么最好将该变量初始化为null而不是其他值。Symbol :(ECMAScript 6 新定义)
1种复杂数据类型:
- Object:ECMAScript中的对象其实就是一组数据功能的集合。对象可以通过执行new操作符后跟要创建的对象类型的名称来创建。Object有三个子类型狭义的对象- 正则表达式(regexp),数组(array),函数(function)。
14.原始类型(或基本数据类型)和复杂类型的区别
1.在内存中的存储方式
(1)基本数据类型把数据名和值直接存储在栈当中。
(2)复杂数据类型在栈中存储数据名和一个堆的地址,在堆中存储属性及值。访问时先从栈获取地址,再到堆中拿出相应的值。
2.不同数据类型作为参数时,函数内部对参数的修改是否改变外部变量的值
情况一:基本数据类型作为参数时,函数内部对参数值的修改不会改变外部变量的值
function a(s){//定义以s为参数的函数,返回s的值
s=100;
return s;
}
var y=1;
a(y);//y作为参数调用函数a
console.log(y);//y还是为1
结果还是1因为把y的值给s时是简单的复制了一份,y和s可以单独操作不相互影响
情况二:复杂数据类型作为参数时,函数内部对参数值的修改会改变外部变量的值
因为复杂数据类型赋值是把栈中对象的地址赋给变量,函数内外两个变量指向同一个对象,所以只要对象的属性值改变,两个变量值都会改变
function student(age,name,agrde){
this.age=age;
this.name=name;
this.score=agrde;
}
var s1=new student(18,"wjq",2);//创建一个student对象
function a(s){
s.name=”xxx”;
}
a(s1)//把s1赋给s
console.log(s1.name);//输出xxx
原始类型和对象(复杂类型)的区别主要还是在内存中的保存形式,要弄懂js中简单数据类型和复杂数据类型的区别,关键还要搞懂两个在内存中的存储过程。
15.求 10000 以内 3 和 5 的倍数和,写出JavaScript实现函数
function sum(n){
var result=0;
for(var i=1; i<=n; i++){
if(i%3==0 && i%5==0){
result+=i;
}
}
return res;
}
16.什么是对象
ECMA-262把对象定义为:无序属性的集合,其属性可以包含基本值、对象或者函数。
严格来讲,这就相当于说对象是一组没有特定顺序的值。对象的每个属性或方法都有一个名字,而每个名字都映射到一个值。正因为这样,我们可以把对象想象成散列表:无非就是一组名值对,其中值可以是数据或函数。
17.构造函数与其他函数的区别
构造函数与其他函数唯一的区别,就在于调用它们的方式不同。不过,构造函数毕竟也是函数,不存在定义构造函数的特殊语法。任何函数,只要通过new操作符来调用,那它就可以作为构造函数;而任何函数,如果不通过new操作符来调用,那它跟普通函数也不会有什么两样。
18.DOM对象的innerText和innerHTML有什么区别?
test1 test2
innerHTML
可以用來取得从对象的起始位置到终止位置的全部内容,包括HTML
标签;innerText
也可以用來取得从对象的起始位置到终止位置的全部内容,但是会把其中的 HTML标签去除掉。
特别说明: innerHTML
是符合W3C标准的属性,而innerText
只适用于IE浏览器,因此,尽可能地去使用innerHTML
,而少用innerText
。