javascript深入浅出学习笔记
一.数据类型:
1.对象与对象是不相等的,比如:console.log(new Object() == new Object())//结果是false;console.log([1,2] == [1,2]);//结果是false;但是有一个例外的就是console.log(null === null)//结果是true
2.NaN和NaN是不同的,console.log(NaN == NaN)//结果是false
3.类型检测的几种方法:typeof、 instanceof、 Object.prototype.toString、 constructor、 duck type。
4.typeof返回某对象的原型,typeof obj //
5.instanceof用来判断一个对象是不是另外一个对象的实例,[1,2] instanceof Array(首字母是大写的)//结果是true
6.Object.prototype.toString常用的几个例子:
Object.prototype.toString.apply([]); //=== “[object Array]”;
Object.prototype.toString.apply(function(){}); //=== “[object Function]”;
Object.prototype.toString.apply(null); //=== “[object Null]”;
Object.prototype.toString.apply({}); //=== “[object object]”;
Object.prototype.toString.apply(new Date()); //=== “[object Date]”;
Object.prototype.toString.apply(undefined); //=== “[object Undefined]”;
7.javascrpt隐藏机制:当把一个基本类型以对象的形式去使用的时候,javascript会将其转换为包装类型对象(就是相当于new了一个对象),但是当操作完毕后这个临时包装对象就会被销毁
var a="string";
a.length;//6这里就会转换为包装类型对象,即相当于new String("string"),所以这里拥有length属性
a.t=3;
alert(a.t);//undefined,t已经被销毁了,所以是undefined
调用它属性时会临时创建对象,调用完后就销毁,创建它的t属性时,也会创建临时对象,但创建完t属性后就销毁了,然后你再调用t属性,又会创建临时对象,但此时t是木有的.
同样这种方法也是针对number(var nu = new Number(123)/new Number('123')对象,boolean对象的. 二.表达式和运算符:
1.删除对象的属性使用delete
var obj = {x:1};
obj.x;//1
delete obj.x;//true
obj.x//undefined
但是ie9之后就会使用defineProperty这样一个方法来控制删除
var obj = {};
Object.defineProrperty(obj,"x",{
configurable:false, //就是表示不能删除
value:1
});
delete obj.x;//false
obj.x; //1
2.void运算符返回的都是undefined,比如:void(0)//undefined void("123")//undefined 三.语句,严格模式
1.块语句:块语句常用于组合0~多个语句,块语句用一对花括号定义.(需要注意的一点是没有块级作用域)比如:
{语句1;语句2;...语句n},if(true){console.log(123)},for(var i=0;i<19;i++){...}等
因为没有块级作用域,所以for(var i=0;i<19;i++){...}等价于var i=0;for(;i<29;i++){...}所以我们可以看出for循环中变量i是全局变量
需要注意的一点是,区分函数作用域和块语句:
函数作用域: function foo() {
var a = 1;//这里a是局部变量,外部不可以访问
console.log(a); // 1
}
foo();
console.log(typeof a); // undefined
块语句:
var a = [];
for (var i = 0; i < 10; i++) { //这里i是全局变量
a[i] = function () {
console.log(i);
};
}
a[6](); // 因为i是全局变量,所以这里值为全局的值10
2.try catch finally
1.1.1 try后面至少要有catch,finally中的一个,所以就有三种方式:
try,catch;try,finally;try,catch,finally;
1.1.2 catch中的语句是在抛出异常之后才去执行的,当让catch中也可以抛出异常
1.1.3 如果有finally,那么不管有没有执行catch都会执行finally的
1.1.4 当try中发生异常时会跳到最近的catch语句中进行处理(这里就是涉及到嵌套)
下面来看几个例子:
try {
try {
throw new Error("oops");
}
finally {
console.log("finally");
}
}
catch (ex) {
console.error("outer", ex.message);
}
执行路径:try(抛出异常) => finally(虽然抛出了异常,但是这里要先执行finally) => catch
所以这里的结果是:"finally" "outer" "oops"
try {
try {
throw new Error("oops");
}
catch (ex) {
console.error("inner", ex.message);
}
finally {
console.log("finally");
}
}
catch (ex) {//因为上面已经执行了catch来处理异常了,所以这里的catch是不会再执行了
console.error("outer", ex.message);
}
执行路径:try => catch(内部的) => finally
执行的结果:"inner" "oops" "finally"
try {
try {
throw new Error("oops");
}
catch (ex) {
console.error("inner", ex.message);
throw ex;//这里又抛出了异常,所以会执行最后面的那个catch
}
finally {
console.log("finally");
}
}
catch (ex) {
console.error("outer", ex.message);
}
执行路径:try => catch(内部的) => finally => catch(外部的)
执行结果:"inner" "oops" "finally" "outer" "oops"
3.函数的声明function f(){...};函数的表达式var f = function f(){...};
函数声明可以被预先处理,也可以叫函数前置,比如:
f();//true
function f(){...} fe();//TypeError
var fe = function(){...}
4.for in
特点:顺序不确定,enmuerable为false时不会出现,for in对象属性时是受原型链影响
5.switch语句:
1.1 default是当所有的case都不满足时去执行default语句
1.2 如果没有break语句,那么switch语句会从满足case的地方一直顺序执行到结束
6.严格模式
不允许未声明的变量被赋值;
不允许使用with;
arguments变为参数的静态副本,这里有几个重要的例子:(! function (){}(1) 表示该函数是一个函数表达式而不是函数声明,后面的(1)是将参数1传递进去,前面的!,你可以理解成它是将函数声明转化成函数表达式的一种方法。
!function (){}(1)也等同于(function (){})(1);,!也可换成+、-这样的一元运算符,都可以起到相同的作用。
函数也是一种对象,arguments是它的一个属性,函数的属性还包括name,length等等,arguments是参数对象的意思,不用写形参在函数上,也可以获取到函数上放进来的实参,利用arguments.length来获取参数个数,arguments[0],来获取第一个实参.)
!function(a){
arguments[0] = 100;
console.log(a);//这里的结果是undefined
}()//这里没有传入参数,所以输出的结果是undefined !function(){
arguments[0] = 100;
console.log(a);
}(1);//这里虽然传入了参数,但是回报错,因为a没有定义 !function(a){
arguments[0] = 100;//非严格模式下,arguments是和传入的参数有帮定的,所以这里arguments[0]就是代表a
console.log(a);//这里结果是100
}(1); 'use strict';
!function(a){
arguments[0] = 100;
console.log(a);//这里结果是1,因为严格模式下,arguments成为了静态副本,不再和a有绑定
}(1); 'use strict';
!function(a){
arguments[0].x = 100;
console.log(a.x);//这里输出来的是100,因为在严格模式下,如果传入的参数是对象的话,修改arguments属性是会对传入参数属性会影响的
}(x:1);
7.delete参数,函数名报错
!function(a){
'use strict';
delete a;//这里会报错,如果是非严格模式下,结果为false
}(1);
8.delete不可配置的属性报错
!function(a){
'use strict';
var obj = {};
Object.definePrperty(obj,"a",{configurable:false});
delete obj.a;//这里会报错TypeError
}(1);
9.对象字面量重复属性名报错.
10.禁止八进制字面量.
11.eval, arguments变为关键字,不能作为变量、函数名
三、对象
1、对象包含一系列的属性,这些属性是无序的,每个属性都有一个字符串key和相对应的value。
2、对象中访问属性的顺序:某一实例对象obj => foo.prototype => Object.prototype => null,所以下面的typeof obj.toString 返回的是'function',
当访问对象属性时,会一直按上面的方式往上面查找,如果一直没有找到,就返回undefined
3、如果是赋值的话就不会像上面一样往上面查找,只会在本对象上查找,如果没有找到就创建一个,所以不会改变原型链上的值,同样delete可以用来删除属性,但是它只会删除本对象上的属性,不会修改掉原型链上的属性。
4、可以使用Object.create({x:1})来创建一个对象的属性,var obj = Object.create({x:1});这句话的意思就是在原型{x:1}中创建一个对象obj,所以obj的原型是{x:1}。如果使用成这样,那么这个属性是属于(原型是)null上的,所以没有任何方法。
5、for in 循环中因为使用的是in,所以这个循环可能会把原型链上的属性都遍历出来了,但是如果是原型链上的花只能是原型链上可以枚举的属性(一般来说原型链上的属性是不可枚举的),就是说遍历原型链上enumerable为true的属性,如果是false的,for in仍然是遍历不出来的。
var o = {x : 1, y : 2, z : 3};
'toString' in o; // true
o.propertyIsEnumerable('toString');// false 我们可以使用这个方法来查看某个属性是否是可枚举的
var key;
for (key in o) { console.log(key); // x, y, z 这里就只会for in出可以枚举的属性
}
一般使用Object.create来创建的属性是可以枚举的。比如:
var obj = Object.create(o); obj.a = 4; var key; for (key in obj) { console.log(key); // a, x, y, z }
所以我们可以使用下面的方法来for in只属于本对象的属性。
var obj = Object.create(o); obj.a = 4; var key; for (key in obj) { if (obj.hasOwnProperty(key)) { console.log(key); // a } }
6、对于delete,可以用来删除对象上的一些属性,但是并非所有的属性,比如:
1.1、delete Object.prototype;就会报错,表示不可以删除这个属性,我们可以使用var descriptor = Object.getOwnPropertyDescriptor(Object,"prototype");descriptor.configurable;//false 的方式来查看原型上的某个属性标签为true还是false来判断该属性是否是可枚举的(这里是查看Object.prototype),结果为false,所以不可以枚举。
1.2、全局变量用var 来声明的变量不可以delete删除,但是隐式的创建变量,然后使用window的变量是可以删除的,比如:a = 1;window.a//1 delete a //true.同样声明的函数不可以删除。
7.对象的属性标签:writable,enumerable,configurable,get/set,value等。
8.2)属性操作
对象里的属性有如下特性:
数据属性:
configurable:设置属性是否能被删除,属性的特性是否能被设置,能否修改属性的值等;
enumerable:设置属性是否可枚举
writable:设置属性的值能否被修改
value:设置属性的值
在添加一个对象的属性时默认上面的特性都为
true
,而value则是属性的值,如果想通过自定义这些特性来设置对象属性,可以通过Object.defineProperty,如下:
var
person = {name:
"张三"
};
Object.defineProperty(person,name,{configurable:
true
,enumerable:
true
,writable:
true
,value:
"李四”});
在上面所设置的特性当中,configurable如果为false表示属性特性设置在之后不能被改动(除了writable,writable在configurable为false时仍然可以设置成false),而且configurable一旦为false后就不能再设置成true了,
而enumberable如果为false则表示该属性不可枚举,用for in循环输出对象属性时该属性不会被输出;
writable很明显,为false时则表示不可修改该属性的值(不过当configurable为true时可以通过修改value的值直接改写或者将writable修改为true)
Object.defineProperty(person,name,{configurable:false});
delete person.name; //delete操作不成功
Object.defineProperty(person,name,{enumerable:false}); //操作不成功
...
访问器属性
configurable:设置属性是否能被删除,属性的特性是否能被设置,能否修改属性的值等;
enumerable:设置属性是否可枚举
get / set :在读写属性时会自动调用的函数
比如:
var book = {
_year:2004,
edition:1
};
Object.defineProperty(book,"
year
",{
get:function(){
return this._year;
},
set:function(newValue){
this._year = newValue;
this.edition += newValue - 2004;
}
});
book.year = 2005; //当要设置year属性时,会自动调用set方法
alert(book.edition);
如果要的不止是配置单单一个属性,而是要同时配置多个,可以通过Object.defineProperties,如下:
var person = {name:"
张三
"};
Object.defineProperty(person,{
name:{value:"
李四”,configurable:
false
},
sex:{value:
"man"
,writable:
false
}
});
在配置完属性后或者通过Object.defineProperty更改过属性后想读者该属性,可以通过Object.getOwnPropertyDescriptor读取
Object.getOwnPropertyDescriptor(book,
"edition"
);
//读取book对象中的edition属性
3)对象标签
[[proto]]:
对象中有个属性[[proto]]指向它的构造器的原型
[[class]]:
看不懂视频里在讲啥- -,没说为啥是通过Object.prototype.toString去获取[[class]]的,所以还是不懂[[class]]的含义
[[extensible]]:
var
obj = {x:1,y:2};
Object.isExtensible(obj);
//检测对象是否可扩展,一般来说默认都是true
Object.preventExtensions(obj);
//禁止对象可扩展
Object.defineProperty(obj,
"x"
,{value:2});
//虽然禁止了对象扩展,但是删除或者修改属性的值以及标签
Object.seal(obj);
//禁止对象属性被删除以及配置属性标签
Object.isSealed(obj);
//判断对象是否被seal
Object.freeze(obj);
//冻结对象,禁止对象属性值被改写
Object.isFrozen(obj);
//判断对象是否被freeze
4)序列化
在向后台发送请求数据时,用JSON.stringify将对象转化为字符串,用JSON.parse将字符串解析为对象
但是,在用JSON.stringify将对象转化为字符串时如果对象属性的值为undefined,那么它将不会出现在转化后的字符串里
如果我们想自定义序列化,可以在对象里自定义toJSON方法,同理,我们在将对象toString或者valueOf时也可以自定义toString方法和valueOf方法
对象转化为基本类型的过程:
在后台首先会自动调用valueOf方法尝试将对象转化为基本类型,如果valueOf不存在或者无法转化为基本类型则会调用toString方法继续尝试,如果两种都无法将对象转化为基本类型则会报错
总结来看:继承的几种方法:
function Person(){}
funciton Student(){}
Student.prototpe.constructor = Student;
1.Student.prototype = new Person();//传参可能有问题
2.Student.prototype = Person.prototype;//这种方法的缺点就是父类和子类的原型都指向了同一个对象,如果改变一个会导致两个都受影响
3.Student.prototype = Object.create(Person.prototype);//注意这种方法是要在ES5之后才能用,但是时最实用的,所以我们引出了第四种
4.if(!Object.create){
Object.create = function(proto){
function F(){}
F.prototype = proto;//proto是原型对象
retrun new F;
};
}
javascript深入浅出学习笔记的更多相关文章
- javascript深入浅出——学习笔记(六种数据类型和隐式转换)
在慕课之前学过JS深入浅出,最近发现很多东西都记不太清楚了,再复习一遍好了,感觉这个课程真的超级棒的,做做笔记,再添加一些学习内容
- javascript深入浅出——学习笔记(包装对象和类型检测)
3包装对象:https://www.imooc.com/video/5676 当我们尝试把基本类型已对象的方式访问时,javascript会把该基本类型转换为对应的包装类型对象(临时对象),相当于ne ...
- JavaScript正则表达式学习笔记(二) - 打怪升级
本文接上篇,基础部分相对薄弱的同学请移步<JavaScript正则表达式学习笔记(一) - 理论基础>.上文介绍了8种JavaScript正则表达式的属性,本文还会追加介绍几种JavaSc ...
- javascript正则表达式 - 学习笔记
JavaScript 正则表达式 学习笔记 标签(空格分隔): 基础 JavaScript 正则表达式是用于匹配字符串中字符组合的模式.在javascript中,正则表达式也是对象.这些模式被用于Re ...
- JavaScript简易学习笔记
学习地址:http://www.w3school.com.cn/js/index.asp 文字版: https://github.com/songzhenhua/github/blob/master/ ...
- javaScript 对象学习笔记
javaScript 对象学习笔记 关于对象,这对我们软件工程到学生来说是不陌生的. 因为这个内容是在过年学到,事儿多,断断续续,总感觉有一丝不顺畅,但总结还是要写一下的 JavaScript 对象 ...
- 【MarkMark学习笔记学习笔记】javascript/js 学习笔记
1.0, 概述.JavaScript是ECMAScript的实现之一 2.0,在HTML中使用JavaScript. 2.1 3.0,基本概念 3.1,ECMAScript中的一切(变量,函数名,操作 ...
- Javascript MVC 学习笔记(一) 模型和数据
写在前面 近期在看<MVC的Javascript富应用开发>一书.本来是抱着一口气读完的想法去看的.结果才看了一点就傻眼了:太多不懂的地方了. 仅仅好看一点查一点,一点一点往下看吧,进度虽 ...
- Javascript作用域学习笔记(三)
看完<你不知道的javascript>上,对作用域的新的理解(2018-9-25更) 一.学习笔记: 1.javascript中的作用域和作用域链 + 每个函数在被调用时都会创建一个 ...
随机推荐
- maven更换下载镜像源-解决下载慢问题
Maven是当前流行的项目管理工具,但官方的库在国外经常连不上,连上也下载速度很慢.国内oschina的maven服务器很早之前就关了.今天发现阿里云的一个中央仓库,亲测可用. 1 <mirro ...
- git diff提示filemode发生改变解决办法
git diff提示filemode发生改变(old mode 100644.new mode 10075) Posted on 2016-11-15 16:55 我是孙海龙 阅读(2292) 评论( ...
- 通过Collections将集合转换为线程安全类集合
通过Collections将集合转换为线程安全类集合 List集合: List<String> list=new ArrayList<String>();list.add(&q ...
- tyvj 1067 合唱队形 dp LIS
P1067 合唱队形 时间: 1000ms / 空间: 131072KiB / Java类名: Main 背景 NOIP2004 提高组 第三道 描述 N位同学站成一排,音乐老师要请其中的(N ...
- 关于分析web.xml的一篇博客,写的很详细
http://blog.csdn.net/believejava/article/details/43229361
- 给virtualbox里linux添加共享文件夹
首先,必须要有已经在VirtualBox中安装好的Ubuntu系统,才能按照以下步骤操作,具体怎样在VirtualBox中安装Ubuntu系统百度经验里已经有很多,大家可以自己查询参照. 打开虚拟 ...
- 实际工作中遇到关于Struts2线程安全的问题解决
今天工作遇到一个难缠的bug,浪费了2个小时终于解决. 问题描述:对资源的管理中用到关键字查询以及分页查询.视图控制器用到struts2,数据存储用spring的data-mongodb来存储数据以及 ...
- 分享知识-快乐自己:List 集合去重合并 , 多种方法演示
最近空闲时间去面试 , 被问了一个问题list如何去重合并 , 想了半天只想到了最繁琐的循环方法 , 顿觉丢人. 整理一下资料供大家参考: List<String> a = new Arr ...
- 【scala】集和映射
Scala同时提供了集(Set)和映射(Map)的可变和不可变的不同选择,但使用同样的简单名字,可以通过类继承的关系来区分可变和不可变版本. 如图所示,左边的为不可变集,右边的为可变集. //我们创建 ...
- 在一个Activity中启动另一个Activity
一.新建一个空的工程 二.添加一个Activity并命名为BAty 三.在activity_main.xml中添加一个按钮,设置id号为btnStartB <Button android:lay ...