可简单概括为:ECMAScript是JavaScript的规范,JavaScript是ECMAScript的实现。
红宝书第一章小结:
js是一种专为与网页交互而设计的脚本语言,由下列三个不同部分组成:
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)。日常场合,这两个词是可以互换的。
1.使用script标签,将javascript代码写到<script></script>之间
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>js使用方式2:内部js</title>
</head>
<body>
<input type="button" value="点击有惊喜" onclick="surprise()"><!--调用函数-->
<input type="button" value="点击" onclick="surprise()">
<script type="text/javascript">
//声明一个函数(整个文档都可以使用)
function surprise() {
alert('恭喜你中了一百万')/*弹出框*/
}
</script>
</body>
</html>
2.添加外部javascript文件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>js使用方式3:外部js</title>
<!--很多html页面都可以调用js4.js页面-->
<script src="../../js/js4.js" type="text/javascript" charset="utf-8">
</script>
</head>
<body>
<input type="button" value="点击" onclick="test()">
</body>
</html>
3.使用行内javascript
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>js使用方式1:行内js</title>
</head>
<body>
<input type="button" value="点击有惊喜" onclick="javascript:alert('哈哈哈哈')">
<!--onclick:点击触发一个事件,alert:弹出一个对话框-->
</body>
</html>
javascript 语言特性中,有很多方面和我们接触的其他编程语言不太一样,比如说,javascript语言实现继承机制的核心就是 ___,而不是Java语言那样的类式继承。
Javascript 解析引擎在读取一个Object的属性的值时,会沿着 ___向上寻找,如果最终没有找到,则该属性值为 ___; 如果最终找到该属性的值,则返回结果。
与这个过程不同的是,当javascript解析引擎执行“给一个Object的某个属性赋值”的时候,如果当前Object存在该属性,则改写该属性的值,如果当前的Object本身并不存在该属性,则赋值该属性的值 。
1.什么是原型,原型有什么特点:
JavaScript 的每个对象都继承另一个对象,后者称为“原型”(prototype)对象。只有null除外,它没有自己的原型对象。
使用原型的好处是:原型对象上的所有属性和方法,都能被对应的构造函数创建的实例对象共享(这就是 JavaScript 继承机制的基本设计),也就是说,不必在构造函数中定义对象实例的信息,而是可以将这些信息直接添加到原型对象中。
每一个构造函数都有一个prototype(原型)属性,这个属性就是使用构造函数创建出来的实例对象的原型对象。
2.什么是原型链,原型链有什么特点
对象的属性和方法,有可能是定义在自身,也有可能是定义在它的原型对象上。由于原型本身也是对象,又有自己的原型,所以形成了一条原型链(prototype chain)。
如果一层层地上溯,所有对象的原型最终都可以上溯到Object.prototype,即Object构造函数的prototype属性指向的那个对象。而Object.prototype对象的原型就是没有任何属性和方法的null对象,而null对象没有自己的原型。
“原型链”的作用是,读取对象的某个属性时,JavaScript 引擎先寻找对象本身的属性,如果找不到,就到它的原型去找,如果还是找不到,就到原型的原型去找。如果直到最顶层的Object.prototype还是找不到,则返回undefined。
如果对象自身和它的原型,都定义了一个同名属性,那么优先读取对象自身的属性,这叫做“覆盖”(overriding)。
需要注意的是,一级级向上,在原型链寻找某个属性,对性能是有影响的。所寻找的属性在越上层的原型对象,对性能的影响越大。如果寻找某个不存在的属性,将会遍历整个原型链。
1.什么是同源?
所谓“同源”指的是”三个相同“。相同的域名、端口和协议,这三个相同的话就视为同一个域,本域下的JS脚本只能读写本域下的数据资源,无法访问其它域的资源。
2.什么是同源策略?
同源策略是浏览器为了保护用户的个人信息以及企业数据的安全而设置的一种策略,不同源的客户端脚本是不能在对方未允许的情况下访问或索取对方的数据信息;
3.同源策略的目的
同源政策的目的,是为了保证用户信息的安全,防止恶意的网站窃取数据。
设想这样一种情况:A 网站是一家银行,用户登录以后,又去浏览其他网站。如果其他网站可以读取 A 网站的 Cookie,会发生什么?
很显然,如果 Cookie 包含隐私(比如存款总额),这些信息就会泄漏。更可怕的是,Cookie 往往用来保存用户的登录状态,如果用户没有退出登录,其他网站就可以冒充用户,为所欲为。因为浏览器同时还规定,提交表单不受同源政策的限制。
由此可见,“同源政策”是必需的,否则 Cookie 可以共享,互联网就毫无安全可言了。
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
借用构造函数的问题:
(。。。。。。。。。来日补充)
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
var person = new Object();
person.name = "junjun";
person.age = 18;
var person = {
name: "junjun";
age: 18;
}
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.
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");
image.png
方法一:
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"
function del(arr) {
for(var i=0;i<arr.length;i++){
for(var j=i+1;j<arr.length;j++){
if(arr[i]==arr[j]){
arr.splice(i,1);
}
}
}
return arr;
}
------------------------------
var a = [1,2,3,4,5,1];
del(a); //[2,3,4,5,1]
最新的 ECMAScript 标准定义了 7 种数据类型:6种原始类型(也称基本数据类型)和1种复杂数据类型。
6种原始类型(也称基本数据类型):
1种复杂数据类型:
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中简单数据类型和复杂数据类型的区别,关键还要搞懂两个在内存中的存储过程。
function sum(n){
var result=0;
for(var i=1; i<=n; i++){
if(i%3==0 && i%5==0){
result+=i;
}
}
return res;
}
ECMA-262把对象定义为:无序属性的集合,其属性可以包含基本值、对象或者函数。
严格来讲,这就相当于说对象是一组没有特定顺序的值。对象的每个属性或方法都有一个名字,而每个名字都映射到一个值。正因为这样,我们可以把对象想象成散列表:无非就是一组名值对,其中值可以是数据或函数。
构造函数与其他函数唯一的区别,就在于调用它们的方式不同。不过,构造函数毕竟也是函数,不存在定义构造函数的特殊语法。任何函数,只要通过new操作符来调用,那它就可以作为构造函数;而任何函数,如果不通过new操作符来调用,那它跟普通函数也不会有什么两样。
<body>
<div id="test">
<span style="color:red">test1</span> test2
</div>
<script>
var test=document.getElementById('test');
console.log(test.innerHTML);//输出 <span style="color:red">test1</span> test2
console.log(test.innerText);//输出test1 test2
</script>
innerHTML
可以用來取得从对象的起始位置到终止位置的全部内容,包括HTML
标签;innerText
也可以用來取得从对象的起始位置到终止位置的全部内容,但是会把其中的 HTML标签去除掉。特别说明: innerHTML
是符合W3C标准的属性,而innerText
只适用于IE浏览器,因此,尽可能地去使用innerHTML
,而少用innerText
。