文章目录
JavaScript笔记
web的发展及浏览器的组成
web的发展
Mosaic,是互联网历史上第一个获普遍使用和能够显示图片的网页浏览器。于1993年问世。
浏览器的组成
- 界面
- 内核
- 渲染引擎:语法规则和渲染
- js引擎
- 其他模块
主要浏览器及内核
浏览器 | 内核 |
---|---|
IE | trident |
Chrome | webkit/blink |
firefox | Gecko |
opera | presto |
safari | webkit |
基本语法
JavaScript的引入方式
-
内嵌式
<!-- 可以嵌套多个JavaScript标签,每个标签互不影响 --> <script> document.write("hello world") </script>
-
文件引入式
<!-- 在引入标签中的代码是不会被执行的,需要可插入新的script标签 -->
<script type="text/javascript" src="Hello.js">
</script>
- 在开发中一般结构,样式,行为相分离,选择第二种形式。
JavaScript语法编写规范
- JavaScript编写的基本规范
var 我 ="猎剑";//JavaScript采用Unicode编码,可以用双字节命名常量,变量,函数等
var name="猎剑";//在开发中一般不建议使用
var Name="张三";//JavaScript对大小写敏感
var
a = " 李四";//代码风格化:JavaScript一般会忽略空格,换行符,制表符.
//这是JavaScript中的单行注释
/*这是JavaScript中多行注释
不会别浏览器解析*/
JavaScript中的常量
- javaScript中不支持用户自定义常量,但是系统提供一些默认常量供开发使用
常量 | 描述 | JavaScript 对象 |
---|---|---|
E | 数学常量 e。 这是欧拉数,即自然对数的底。 | Math |
Infinity | 一个大于最大浮点数的值。 负无穷大 (-Infinity) 小于最小浮点数。 | Global |
LN2 | 2 的自然对数。 | Math |
LN10 | 10 的自然对数。 | Math |
LOG2E | e 的以 2 为底的对数。 | Math |
LOG10E | e 的以 10 为底的对数。 | Math |
MAX_VALUE | 可在 JavaScript 中表示的最大数字。 | Number |
MIN_VALUE | 可在 JavaScript 中表示的最接近零的数字。 | Number |
NaN | 表示算术表达式返回了非数字值。 | Number |
NaN(全局) | 一个指示表达式不是数字的值。 | Global |
NEGATIVE_INFINITY | 一个小于最小浮点数的值。 | Number |
null 常量 (JavaScript) | 不指向有效数据的变量值。 | Global |
PI | Pi. 这是圆的周长与直径的比率。 | Math |
POSITIVE_INFINITY | 一个大于最大浮点数的值。 | Number |
SQRT1_2 | 0.5 的平方根或相等项(即 2 的平方根分之一)。 | Math |
SQRT2 | 2 的平方根。 | Math |
未定义 | 已声明但未初始化的变量的值。 | Global |
JavaScript中的变量
- 变量的声明使用
var name ; //变量声明
name="猎剑" ; //变量赋值
var name,
age,
gender; //同时声明多个变量
console.log(name); // 变量的调用
- 常见的变量类型
- 原始值:Number String Boolean undefind null(一般直接存在栈内)
- 引用值:Object Array function 等(实际数据存在堆内,栈里面存的是堆的引用)
var a=[1,3,5,4,6] //声明a并给a赋值,a在栈里边开辟一块空间存堆里的地址,把自己的数据存在堆里
console.log("*****************************")
var b=a; //a赋值给b,实际上是吧a中存在堆内存地址赋值给b, b:1,3,5,4,6
a.push(9); //a中加入9,实际上就是在堆内存中加入9
/*
a:1,3,5,4,6,9
b:1,3,5,4,6,9
*/
JavaScript中的变量命名规则
-
变量首字母以英文字母、_(下划线)、$ 开头。
-
变量可以包含英文字母、_(下划线)、$ 、数字。
-
不能以JavaScript的关键字、保留字命名变量。
JavaScript中常见的运算符
-
算术运算符
运算符 描述 例子 结果 + 加 x=y+2 x=7 - 减 x=y-2 x=3 * 乘 x=y*2 x=10 / 除 x=y/2 x=2.5 % 求余数 (保留整数) x=y%2 x=1 ++ 累加 x=++y x=6 – 递减 x=–y x=4 -
赋值运算符
运算符 | 例子 | 等价于 | 结果 |
---|---|---|---|
= | x=y | x=5 | |
+= | x+=y | x=x+y | x=15 |
-= | x-=y | x=x-y | x=5 |
*= | x*=y | x=x*y | x=50 |
/= | x/=y | x=x/y | x=2 |
%= | x%=y | x=x%y | x=0 |
- 提示
var a = 4;
var b = 3;
var c = a+b;//表示数学中的加
var d = "abc" + "bacd";//表示字符串的连接
-
比较运算符
运算符 描述 例子 == 等于 x==8 为 ture === 全等(值和类型) x===5 为 true;x===“5” 为 false != 不等于 x!=8 为 true > 大于 x>8 为 false < 小于 x<8 为 true >= 大于或等于 x>=8 为 false <= 小于或等于 x<=8 为 true -
逻辑运算符
运算符 描述 例子 && and (x < 10 && y > 1) 为 true || or (x==5 || y==5) 为 false ! not !(x==y) 为 true
var a=(10*3-4/2+1)%2,
b=3;
b %= a+3;
document.write(a++);
document.write("<br/>");
document.write(--b);
JavaScript中的语句
JavaScript中的基本语句规则
- 语句结束要用“ ;”
- js语法错误会影响后续的语句执行,但不会影响其他的语句执行
- 书写要规范
条件语句
- if else语句
if(condition){
statement
}else if(condition){
statement
}else{
}
var a = 58;
if(a>80){
document.write("very good");
} else if( a>60){
document.write("good");
}else{
document.write("come on");
}
-
switch case 语句
switch(变量){ case 常量1: 执行代码。 break; case 常量2: 执行代码。 break; default: 执行代码。 break }
var input = window.prompt("输入星期几");
switch (input) {
case "Monday": //判断input是否等于 Monday 如果等于往下执行,直到遇到 break 或 reutrn。
case "Tuesday": //没有 break 或 return 则继续往下执行
case "Wednesday":
case "Thursday":
case "Friday":
document.write(input,"需要工作!");
break; //中断 switch
case "Saturday":
case "Sunday":
document.write(input,"休息~!~");
break; //中断 switch
default: //如果未匹配到则执行 default 代码段。
document.write("输入的信息不正确");
break;
循环语句
-
while循环
while(condition){ statements }
var a = 4;
while (a>10){ //条件为真才会执行
document.write(a);
a++;
}
- do while 语句
do{
statements
}while (condition)
var a = 4;
do{
document.write(a);
a++;
}while (a>10);//无论条件是否为ture语句都会被执行一次
- for 语句
for(condition){
statements
}
for(var i = 0;i<10;i++)
{
document.write(i);
}
- break和continue语句
- break语句:跳出当前循环,不再执行循环
- continue语句:跳出当前循环,执行下一次循环
- 几个小练习
//计算2的n次幂
var a =parseInt(window.prompt("请输入一个数"));
var count = 1;
for(var i = 0;i<a;i++)
{
count=count*2;
}
document.write(count);
//求n的阶乘
var mul=1;
var a = parseInt(window.prompt("请输入一个数字"));
for(var i = 1;i<=a;i++){
mul*=i;
}
document.write(mul);
//斐波那契数列
var a =parseInt(window.prompt("请输入一个数"));
var frist = 1;
var second = 1;
var third = 2;
for(var i = 0;i<a;i++){
frist = second;
second = third;
third = frist + second ;
}
document.write(frist);
//比较三个数的大小
var a =parseInt(window.prompt("请输入一个数"));
var b =parseInt(window.prompt("请输入第二个数"));
var c =parseInt(window.prompt("请输入三个数"));
var max = 0;
if(a>b){
max = a;
} else if(b>c){
max=b;
}else{
max=c;
}
document.write(c);
JavaScript中数据类型
JavaScript中数据类型的分类
-
JavaScript的数据类型可以分为:数值型 ,字符型,布尔型,转义字符,空值,未定义
数值型
//数值型 var a = 10; //可以是整数,负数,和0,可以采用十进制,八进制或十六进制表示 var b = -10; var c = 2.33; var d = 071; //代表八进制71 var e = 0x123A; //表示十六进制的0x9405B; var g = 1.6E; //表示科学计数1.6*10的5次方 /*数字能表示的范围是小数点前16位,小数点后16位 JavaScript中容易出现精度缺失问题 NaN表示数字类型的非数 Infinity //表示无穷大 NaN //表示非数值 */
字符型
~~~javascript
//字符型数字是指用单引号或者多引号括起来的一个或者多个字符
var a = "猎剑";
var b = '猎剑';
~~~
##### 布尔类型
//布尔型只有两个值true或false,在JavaScript中可以用0代表false,非零代表true
var a = true;
var b = false;
var d = 100;
var c = !!d; //把c的值转换为boolean
var e = false;
//注:每个数自己都等于自己只用NaN直接不等于自己
~~~~
##### 转义字符
>\表示转义字符
>
>\b 表示退格
>
>\r 表示回车
>
>\n 表示换行
##### 空值
>空值null 用于定义空或者不存在的引用
>
>空值不等于("")或者零
##### 未定义值
>未给变量赋值只是声明变量,返回值为undefined
##### 提示
~~~javascript
0 //number
NaN //number
"" //String
false //Boolean
null //object
undefind //Undefind
返回值 undefined 为String 类型
~~~~
#### JavaScript中数据类型的转换
1. 显示类型转换
~~~javascript
//数据类型的显示转换
var a =" 123";
var b = parseInt(a); //调用系统方法转换
var c = b.toString();
var d = parseFloat(b);
console.log(a);
var e = Number(a);
var f =Number("123");
var g = String(123);
alert(typeof g);
- 隐式数据类型转换
// 隐式类型转换
// isNaN ()
// ++/— +/-(一元正负)
var a = "123";
var b = +a; //隐式转换为Number类型
// +
var c = "abc" +123; //隐式转换为字符串类型
// */%
// && || !
var d = !"123";//转换为boolean类型
// < > <= >=
// == !=
// 不发生转换 == !==
JavaScript中的函数
函数的定义
function functionName(形式参数){ //function为函数的关键字,JavaScript中函数必须用关键字进行声明
//functionName为指定函数名
//函数的参数可以有多个,参数之间用英文逗号隔开,最多有255个参数
函数语句 //函数的执行语句
return result //(可以没用返回值)
}
functionName(实际参数); //函数的调用,用来调用执行函数
//计算两数之和
function sum(a,b){
var sum = a + b;
return sum;
}
var c = sum(22,33);
函数的两种形式
function sum(a,b){ //函数声明
var sum = a + b;
return sum;
}
var d = function(a,b){ //函数表达式
var sum = a + b;
return sum;
}
var c = sum(22,33); //调用函数声明
var e= d(22,23); //调用函数表达式
alert(e);
函数的参数
function add(a,b){
console.log(arguments[2]);//aruguments系统内部定义的数组用来存储实际参数
return a+b;
}
//JavaScript中没有要求形参个数要与实参个数相同
//多余的实参会被系统内部定义的一个arguments的数组接收
add(23,33,44,55);//结果为55
add(23,"33"); //结果为2233
//如果形参大于实参则未接收参数的形参被定义为undefined
add(23); //结果为NaN
add.length; //用于计算形参个数
立即执行函数
定义:此类函数没用声明,再一次执行后释放,适合用来做初始化工作
//两种标准形式
(function (x){ //第一种形式
alert(x);
})(50); //50在这里代表参数
(function (y){
alert(y);
}(44)); //写在小括号写在里面和外面是一样的
//只用表达式才能被执行
//下面是一些特殊的立即执行函数
function demo(x){
alert(x)
}("不会被执行"); //函数声明加执行符号不会被执行;
+function demo(x){
alert(x)
}("会被执行"); //转换为表达式,具体有+ - !
var a = function test (x){
alert(a);
}(44); //函数可以别执行
函数应用的几个小列子
//实现两数的相加
var a = function (a,b){
return a+b;
}
console.log(a(22,33));
//实现输出一种动物的叫声
var voice =window.prompt("请输入一种动物的叫声");
function Voice(voice){
switch(voice){
case "cat":
return "miaomiaomiao";
case "dog":
return "wangwangwang";
case "fish":
return "bulubulu";
default:
return "animal voice";
}
}
alert(Voice(voice));
//实现n的阶乘
function mul(n){
if(n == 1){
return 1;
}
return n *mul(n-1);
}
alert(mul(5));
//实现斐波那契数列
function fb(f){
var frist = 1 ;
var second = 1;
var thrid = 2;
for(var i = 1;i<f;i++)
{
frist =second;
second = thrid;
thrid = second + frist ;
}
return frist;
}
document.write(fb(5));
作用域
- 定义:变量或函数生效时的区域叫做作用域
var a = 100; //全局变量,能够在全局进行访问
function a(){
var b = 20; //局部变量,只能再函数内部访问,函数外部访问不到
c = 123; //函数执行后变为全局变量
var d = e = 20; //d是局部变量 函数执行后e为全局变量
}
/* 任何变量如果未经声明就直接赋值,此变量就变为全局所有
一切声明的全局变量,全是Windows的属性 */
- 作用域链精讲
- 在JavaScript中每个函数都是一个对象,对象中有些属性我们可以访问有些属性我们不可以访问,这些属性仅供JavaScript引擎使用[[scope]]就是其中一个。[[scope]]就是我们所说的作用域,其中存储了远行期上下文的集合
- 作用域链定义:[[scope]]中所存储的执行期上下文对象的集合,这个集合呈链式,我们把这种链式叫做作用域链
- 执行期上下文:当函数执行时会创建一个叫做执行期上下文的内部对象,一个执行器上下文定义了一个函数执行时的环境,函数每次执行时对应的执行期上下文都是独一无二的,所以多次调用一个函数时会创建多个执行期上下文,当函数执行完毕,执行期上下文就会被销毁
- 查找变量:从作用域的顶端依次向下查找
function a(){ //a 函数被创建时a -->[[scope]]--->0 Global Object
// a 函数执行时 a -->[[scope]]---> 1 Activation Object
// 0 Global Object
function b(){ // b 被创建时 b -->[[scope]] --> 1 Activation Object
// 0 Global Object
// b 函数执行时 b -->[[scope]]---> 2 Activation Object //b 自己的执行期上下文
// 1 Activation Object //a的执行期上下文 // 0 Global Object
var b = 123;
}
var a = 123;
}
b ();
}
var glob = 100;
a();
预编译
- 定义:JavaScript代码在执行时会先进行对代码的粗略解读叫预编译
JavaScript执行的步骤:
- 语法分析
- 预编译
- 解释执行
- 预编译的四个步骤
- 创建AO对象
- 找形参和变量声明,将变量和形参名作为AO的属性名,值为undefined
- 将形参与实参相统一
- 在函数体里找函数声明,值赋予函数体
- 预编译精讲
function fn(a){ //AO{}
var a = 123; //AO{a:function a(){} b:undefind d:function d(){}}
function a(){}
var b =function(){}
function d(){}
}
fn(1);
/* 创建AO对象 //AO{}
找形参和变量声明 //AO{a:undefind b:undefind}
将形参和实参相统一 //AO{a:1 b:undefind}
在函数体里找函数声明,值赋予函数体 //AO {a:function a(){} b:undefind d:function d(){}}
*/
闭包
- 闭包的定义:当内部函数被保存到外部是会产生闭包,闭包会导致原有的作用域链不被释放,造成内存泄露。
function a(){
//函数a执行时-->[[scope]]---> 1 Activation Obect{a:undefind b:function b }
// 0 Global Obejct{c:undefind demo:undefind a: function(){}}
function b{
//函数b执行时->[[scope]]---> 2 Activation Obect{bbb:undefind}
// 1 Activation Obect{a:undefind b:function b }
// 0 Global Obejct{c:undefind demo:undefind a: function(){}}
var bbb = 234;
document.write(aaa);
}
var a = 123;
return b; //内部函数保存到外部产生闭包
}
var c = 100;
var demo = a();
demo();
//函数a在执行完后会被释放,会断自己的作用域链,但是b函数不会释放自己的作用域链,一直捆绑a函数的作用域链
//b函数可以一直保存a函数的作用域链,并任意改变他所保存的a函数的作用域
-
闭包的作用
- 实现公用变量 eg:函数累加器
- 可以做缓存
- 可以实现封装,属性私有化
-
闭包的防范
闭包会导致多个函数公用一个公有变量,如果不是特殊情况,应该尽量减少这种情况的发生
-
闭包的解决
//立即执行函数,闭包保存循环变量 ii 的使用方式。
function test(){
var arr = [];
for (var i = 0; i < 10; i++) {
(function(ii){
arr[ii] = function(){
document.write("i = " + i + " ii = " + ii + "<br/>")
}
}(i))
}
return arr;
}
var myArr = test();
for(var j = 0;j < myArr.length;j++){
myArr[j]();
}
对象
定义:JavaScript中,对象是有new运算符生成,生成对象的函数被称为类(或者构造函数,对象类型)
//系统内置的几个构造函数
var a = new Object(); //系统内置的原型对象
var date = new Date();//构造日期对象
var p= new RegExp("ab+c","i"); //构造正则表达式对象
</script>
//使用对象字面量定义对象
var obj = { //定义对象
name:"猎剑", //定义属性
sex: "man",
health:100,
somke:function (){
console.log("somking");
this.health ++;
},
drink:function (){
console.log("drinking");
this.health --;
}
};
obj.wife ="小仙女"; //增加对象属性
delete obj.name ; //删除对象属性
document.write("my health is "+obj.health);
obj.somke();
document.write("my health is "+obj.health);
//使用系统内置对象定义
var Person = new Object();
Person.name = '猎剑';
Person.age = 18;
Person.smoke = function (){
document.write("I am smoking");
}
document.write(Person.age);
Person.smoke();
//使用自定义函数创建对象
function Car(color){
//采用大驼峰命名方式
this.color = color;
this.name="BMW";
this.height=500;
this.site=4;
this.run = function (){
document.write(this.name+"Runing");
}
}
var car = new Car("blue");
car.run();
document.write(car.color);
var car1 = new Car("red");
car1.run();
//对属性名的增删查改
function Father(){} //定义一个构造函数
var father = new Father();//声明一个对象
father.lastName = "zhang";//增加一个属性,并赋初值
console.log(father.lastName);
father.lastName = "李";//修改属性值
console.log(father.lastName);
var name = father.lastName;//读取属性值
console.log(name);
delete father.lastName;//删除属性
console.log(father.lastName);
包装类
// 把基本数据用引用类型包裹起来,添加一些属性和方法,以便于操作基本数据类型。如Js系统内置的:Boolean、Number和 String
//系统提供原始数据类型的包装类,使用包装类转换后原始值就变为引用类型。可以有属性和方法。
//经过包装类包装的原始值,具有原始值的功能。
//使用属性访问器试图访问原始值属性时,会隐式把原始值转为引用类型,实际上这个操作并不是操作原始值。
var demo = "abcdef";//变量的类型按照第一次赋值时的类型确定的。这里是字符串类型。
demo.name = "aaaaaa";//隐式转为引用类型并给引用类型的属性赋值,但没有任何变量存储这个引用类型,所以这句执行后引用对象自动销毁。
console.log(demo.name);//隐式转为引用类型并获取引用类型的属性,但这个引用类型的name属性并没有赋值。
var str = new String("abcd");//把字符串转换为引用类型,这个操作就是包装,String是包装类。
var num = new Number(123);
var bool =new Boolean(0);
console.log(str,num,bool);
原型
- 定义:原型是function对象的一个熟悉,他定义了构造函数制造出对象的公共祖先,通过该构造函数产生的对象,可以继承该原型的属性和方法。原型也是对象,利用原型的特点概念可以提取公共属性。
//原型是函数的祖先,比如人类的祖先,遗传给后代人类相貌体征,祖先能够提供属性和方法供后代继承
// Person.prototype 原型
// Person.prototype = {} 祖先
Person.prototype.name = " 猎剑"; //为Person的祖先增加一个属性
Person.prototype.say = function (){
console.log("hehe");
}
function Person(){
}
var person = new Person();
console.log(person.name); //通过person调用他祖先的属性
var person1 = new Person();//同样继承了Person.prototype的属性,所以prototype是这些对象的公有祖先
person1.say();
//原型的另一种写法
Person.prototype = {
LastName: '猎剑',
say: function (){
console.log("hehe")
}
}
function Person(){
}
var person = new Person();
person.say();
Constructor
定义:constructor是构造函数的一个属性,用于指向他的原型
function Person(){
}
Car.prototype = {
constructor : Person //改变他的原型模型指向
}
function Car(){
}
var car = new Car();
原型链
function Person(){
// this {
// __proto__:Person.prototype //__proto__是系统化默认的指向的原型,
//原型的——prototype指向原型
var Obj = {} //原型是 Object.prototype
// };
}
//Object.Creat(原型);
var person = new Person();
//var obj = Object.Creat(原型);
var obj = {name:'猎剑',age:18};
var obj1 = Object.create(obj); //创建对象obj1,obj1的原型是obj
//绝大多数的原型都是Object.prototype
var obj2 = Object.create(null); //obj2没有原型
call/apply
- 作用:改变this指向
- 传参不同
function test(){
}
//test()----> test.call(); 实际是调用test.call执行
//call的作用是改变this指向
function Person(name,age){
//this == obj
this.name = name;
this.age =age;
}
var obj = {
}
//第一位传的是this指向,后面传的是参数
Person.call(obj,"猎剑",20);
function Person(name,age,sex){
this.name = name ;
this.age = age ;
this.sex = sex ;
}
function Student(name,age,sex,grade,tel){
Person.call(this, name, age,sex)
this.grade = grade;
this.tel=tel;
}
var student = new Student(" 猎剑",18,'man','100','18208891933');
function Person(name,age,sex){
this.name = name ;
this.age = age ;
this.sex = sex ;
}
function Student(name,age,sex,grade,tel){
Person.apply(this, [name, age,sex]);
this.grade = grade;
this.tel=tel;
}
var student = new Student(" 猎剑",18,'man','100','18208891933');
//call和apply的区别
// call传的是对应的形参
// apply传的是argument数组
继承
-
传统形式 -—>原型链
缺点:过多继承没用的属性
-
借用构造函数继承
缺点:不能继承借用构造函数的原型
每次构造函数都要多走一个函数
-
共享原型
不能随便该公自己的原型
//原型链式继承
Person.prototype.LastName = "猎剑";
function Person(){
}
function Son (){
}
function inherit(targrt,origin){
targrt.prototype = origin.prototype;
}
inherit(Son,Person);
var person = new Person();
var son = new Son();
Son.prototype.LastName = 'liejian';
//直接把Person.prototype的原型改了,因为两者指向同一个空间
- 圣杯模式继承
//原型链式继承
Person.prototype.LastName = "猎剑";
function Person(){
}
function Son (){
}
function inherit(target,origin){
function F(){}
F.prototype = origin.prototype;
target.prototype = new F();
target.prototype.constructor = target;
target.prototype.uber = origin.prototype; //说明他直接继承自那个类
}
inherit(Son,Person);
var person = new Person();
var son = new Son();
Son.prototype.LastName = 'liejian'; //改了以后只是自己的继承类F增加了属性,而不会影响到自己的Father
命名空间
作用:管理变量,防治污染全局,适合用于模块化开发
var name = "猎剑"; //全局变量
var initName = (function () {
var name = 'liejian'; //定义函数内部变量
function getName(){
console.log(name);
}
return getName;
}());
initName(); //访问自己变量的name值
console.log(name); //访问全局变量
一些知识点小结
- 实现链式调用
function Person(){
this.name ='猎剑';
this.age = 18;
this.smoke = function (){
console.log("Somking");
return this;
}
this.drink = function (){
console.log("DrinKing");
//return undefind 默认返回undefined
return this;
}
this.herm = function (){
console.log("Hreming");
return this;
}
}
var person = new Person();
person.smoke().herm().drink(); //实现链式调用
- obj.prop ----> obj[“prop”]
function Person(){
this.name ='猎剑';
this.age = 18;
this.smoke = function (){
console.log("Somking");
return this;
}
this.drink = function (){
console.log("DrinKing");
//return undefind 默认返回undefined
return this;
}
this.herm = function (){
console.log("Hreming");
return this;
}
}
var person = new Person();
person.smoke().herm().drink();
console.log(person.name);
console.log(person['name']);//在底层抽象成person['name'];
- 对象枚举
function Person(){
this.name ='猎剑';
this.age = 18;
this.smoke = function (){
console.log("Somking");
return this;
}
this.drink = function (){
console.log("DrinKing");
return this;
}
this.herm = function (){
console.log("Hreming");
return this;
}
}
var person = new Person();
for (var prop in person){
// console.log(prop);
// console.log(person.prop);//输出结果为undefined,系统会去寻找里边的person.prop属性
console.log(person[prop]); //输出对象里边的值
}
- instanceof 与hasOwnPropraty
// instanceof 是布尔类型的判断,用来查询该原型是不是在此函数的原型链上
[] instanceof Array //返回值为true
hasOwnPropraty //用来查询他直接原型链上的属性和方法
this的作用
-
函数预编译过程中this–>window
-
全局作用域里this–>window
-
cayll/apply可以改变函数远行时的this指向
-
谁调用this指向谁
var name = '111';
var a = {
name:"222",
say:function (){
console.log(this.name);
}
}
var fun = a.say;
fun(); //this指向全局 111
var b = {
name: "333",
say: function (fun){
fun(); //没有this. 所以走预编译环节
}
}
b.say(a.say);
b.say=a.say;
b.say(); //this 指向b //333
arguments
定义:arguments是函数内部定义的一个用于存函数实参的数组
var mul = (function(n){
if(n==1){
return 1;
}
return n*arguments.callee(n-1);
//argunments.callee用于指向函数的引用,可用于立即执行函数的递归调用
}(20))
//func.caller 用于指向函数的调用者空间
克隆
var obj = {
name:"猎剑",
age: 18,
wife:{
name:"小杨",
age: 18
},
card:["abc","xys"]
}
function deepClone(origin,target){
var target = target || {},
toSt=Object.prototype.toString,
arrStr = "[object Array]";
for(var prop in origin){
if(origin.hasOwnProperty(prop)){
if(origin[prop]!=="null"&& typeof(origin[prop])=="object"){
target[prop] = toSt.call(origin[prop])== arrStr ? []:{};
deepClone(origin[prop],target[prop]);
} else{
target[prop]=origin[prop];
}
}
}
}
var obj1 = {};
deepClone(obj,obj1);
数组
数组的创建方法:
var a = [1,2,3]; //字面量创建
var b = new Array(1,2,3); //调用构造函数创建
//区别
var a = [10]; //a[i]= 10
var b = [10]; //b.lenght = 10 b[i]= undefined
数组的常用方法:
- 改变原数组的方法 :reverse , sort, push, pop,unshift,shift ,sp
//改变原数组的方法 reverse , sort, push, pop,unshift,shift ,splice
var arr = [1,2];
arr.push("3" , "4"); // 从低arr.length位开始增加 arr[1,2 ,'3','4']
//arr.reverse(); //反转数组 arr["3","4",2,1]
arr.pop(); //将最后一位取出 arr[1,2,“3”];
arr.unshift(0); //在数组前增加arr[0,1,2,“3”]
arr.shift();//将数组的第0位去掉arr[1,2,“3”];
arr.splice(1,2,"9","8");//splice 从第几位(负数为倒序操作),截后面取多少位,在切口处添加元素
//arr[1,"9","8"]
arr.sort(function(a,b){ //对数组进行排序 ,里面函数的作用是如果返回值为正,后面那个数就在前边
//如果放回值为负数前面数就在后面
return a - b; // 升序
return a - b ; //降序
})
- 不改变原数组的方法:concat、join、split、toString、slice
//- concat、join、split、toString、slice
var a = [1,3,4];
var b = [2,4,6];
var c = a.concat(b); //作用连接两数组,必须用新数组来接收其返回值
var d = a.join("$"); //将数组以$方式拼接为字符串
var e = d.split("$");//将字符串以$的为间隔拆成数组
var f = a.toString(); //将数组打印输出
var g = a.slice(1,5);
//slice 截取数组从第几位(负数倒序)到第几位(没有第二个参数则截取到结尾)。可以作为转换数组的方法(不填参数)
类数组
/*可以用操作对象的方法对他进行操作
也可以用操作对象的方法对他进行操作
arguments就是典型的类数组*/
// .可以利用属性名模拟数组的特性
// 可以动态的增长length属性
// .如果强行让类数组调用push方法,则会根据length属性值的位置进行属性的扩充
var obj = {
0:'a',
1:'b',
2:'c',
3:'d',
name: '猎剑',
age :18,
length:4, //必须有length属性
push:Array.prototype.push,
splice:Array.prototype.splice
}
obj.push('e'); //加入在数字后面
for (var prop in obj){
console.log(obj[prop]);
}
for(var i = 0; i<obj.length;i++) {
console.log(obj[i]);
}
//实现自己的typeof方法
var template = {
"[object Array]":"array",
"[object Object]":"object",
"[object Number]":"number-object",
"[object Boolean]":"boolean-object",
"[object String]":"string-object"
}
function type(target){
var rel = typeof(target);
if(rel =='null'){
return "null";
}else if(rel == "object"){
var str = Object.prototype.toString.call(target);
return template[str];
}else{
return rel;
}
}
//实现数组的去重
Array.prototype.unqie = function (){
var temp = {},
arr = [],
len = this.length;
for( var i = 0;i<len;i++){
if(temp[this[i]]==undefined){
temp[this[i]]="abc";
arr.push(this[i]);
}
}
return arr;
}
arr = [1,1,1,3,3,3];
var a = arr.unqie();
try …catch
console.log("hello world")
try{
//用作异常处理
console.log("我会被执行");
console.log(a);//发生报错 a is not defined
console.log("我不会被执行"); //异常已下代码不会被执行
}catch(e){
console.log("我是异常后处理的代码"); //发生异常后执行的代码
console.log(e.name + " : " + e.message); //抛出错误信息
}
Error.name 对应的错误信息
- EvalError:eval()使用与定义不一致
- RangeError:数值越界
- ReferenceError:非法后不能识别的引用数值
- SynataxError :发生语法解析错误
- TypeError :操作数类型错误
- URlErro:URl 处理函数使用不当
Es5严格模式
-
浏览器在解析的时候一般是采用es3的标准方法,外加es5新增的方法,如果启用es5标准模式那么就会采用es5的方法。
-
启动es5严格模式
" use strict" ; //在全局的第一行写改字符串,代表启用Es5的严格模式必须是第一行代码
function Demo (){
" use strict"; //表示在函数内部使用es5 严格模式,必须是第一行代码
}
3.es5严格模式的规则:
不再兼容es3的一些不规则语法。使用全新的es5规范。
两种用法:
全局严格模式
局部函数内严格模式(推荐)
就是一行字符串,不会对不兼容严格模式的浏览器产生影响。
不支持with,arguments.callee,func.caller,变量赋值前必须声明,局部this必须被赋值(Person.call(null/undefined) 赋值什么就是什么),拒绝重复属性和参数
默认全局的this为Window,局部的this为undefined