Javascript深入浅出
出处:慕课网教学视频笔记
https://www.imooc.com/learn/277
书籍介绍:
《javascript权威指南》https://developer.mozilla.org/zh-CN/docs/learn/JavaScript
一、数据类型
- 原始类型:null、undefined、number、string、boolean
- 对象类型:object
- null和undefined
1、 null和undefined都是表示没有的、不存在的值。它们两个在进行逻辑转换时都是false,这两个值进行比较是true。
2、 null表示空引用,它是object类型。undefined表示未定义, 它是undefined类型。
3、 一个变量未定义,或一个变量定义了未赋值,则是undefined,如果用typeof去运算,那它的类型也是undefined。
5、 对说属性来说:如果原来没有这个属性,根本就不存在这个属性,那么它的值就是undefined。
6、 如果这个对象以后要用,但是现在还没有值,一般情况下,会给它一个null值。
7、 在函数(方法)里,如果必须返回值,但是值又计算不出来,那就返回一个null(这是规范,而不是语法规定,JAVASCRIPT里遵循这一规范)
Null 类型是第二个只有一个值的数据类型,这个特殊的值是null。从逻辑角度来看,null 值表示一个空对象指针,而这也正是使用typeof 操作符检测null 值时会返回"object"的原因
- 三种强制转换和两种隐式转换
== 内容一致
===类型,内存地址和内容一致
类型相同,同===
类型不同,尝试类型转换后再比较
- javascript包装对象
- 类型检测
typeof 适合六种基本数据类型
instanceof 判断对象类型比如数组,基于原型链,判断左边操作数对象的原型链是否有右边的构造函数的prototype属性
obj instanceof Object
obj:对象
Object:函数对象,函数构造器
注意:不同window或不同iframe间不能用instanceof
Object.prototype.toString.apply(传要判断的参数)
null的检测建议采用严格===
二、表达式
- 表达式
10*20
[1,2]
{a:1,b:2}
var fn = function(){
}
var obj = {a:1,b:2}
obj.a或者object['a']
调用表达式fn()
- 运算符
in 、new、this 、void
void(0):无论后面是啥都返回undefined
三、语句
- block、var等语句
javascript没有块级作用域
- try-catch-finally
- 函数、switch、循环for...in
- javascript的严格模式
会出错的:with语法、没有声明的变量不能被赋值、delete参数、函数都报错、delete配置属性报错、对象在同一个域内不能定义多个参数、禁止八进制字面量、eval不能变成关键字
typeError
四、对象
- 对象概述
obj.x在自身找得到,obj.z自身找不到,就会往原形上找,直到原型链的末端,没找到就是undefined
- 创建对象、原型链
1、创建对象-字面量
var obj={}
obj.x = 1
2、创建对象-new/原型链
z是从原型继承而来的,不是obj自己的属性
原型不受删除、修改等影响
3、对象创建-Object.create(系统内置函数)
var obj = Object.create({
x:1
})
obj.x // 1
直接是继承原型的,不属于obj自己的属性
原型链的末端是null,也就不包含任何属性和方法了
所以如果var a = Object.create(null),a.toString()是undefined
- 属性操作
1、属性读写异常,如何做判断做保护
var flag = obj&&obj.x&&obj.y(保证每个属性存在才能作为正确条件)
2、属性删除
delete Object.prototype 是false不能删除,不存在
delete person.age 是true(无论是否存在,所以可以重复写删除语句)
总的来说有些属性不允许删除,每一个属性都有一系列标签
这个方法可以查询属性的所有标签,就是属性描述器,是不是可配置
var定义的全局变量、函数等都不可以删除、eval里面定义的可以删除
3、属性检测
判断属性是否存在,或者是否可枚举
- get、set方法
console.log('=========属性get/set方法=========')
var man = {
name:'zhengjiechun',
weibo:'@jiechun',
$age:null,
get age(){
if(this.$age == undefined){
return new Date().getFullYear() - 1993
}else{
return this.$age
}
},
set age(val){
val = +val //利用一元+操作符的特性(会尝试转换为数字),来隐式将一个变量转换为数字类型(number)
if(!isNaN(val)&&val>0&&val<150){
this.$age = +val
}else{
throw new Error('Incorrect val = '+val)
}
}
}
console.log(man.age) //25
man.age = 100
console.log(man.age) //100
//man.age = 'abc' //抛出错误
//get set和原型链结合console.log('=========get set和原型链结合=========')function foo(){}Object.defineProperty(foo.prototype,'z',{get:function(){return 1}})var obj = new foo()console.log('obj.z = >',obj.z)obj.z = 10console.log('obj.z = >',obj.z)Object.defineProperty(obj,'z',{value:100,configurable:true, //默认不可配置false,就不可以删除writable:true //默认不可写false})console.log('obj.z = >',obj.z) //100obj.z = 'slslsl'console.log('obj.z = >',obj.z) //slslsl设置为可写了delete obj.zconsole.log('obj.z = >',obj.z) //1又找回原型了
console.log('=========属性标签=========')var person = {}Object.defineProperty(person,'name',{configuration:false,writable:false,enumerable:true, //是否可枚举,就是可否遍历value:'zhengjiechun'})Object.defineProperty(person,'age',{configuration:false,writable:false,enumerable:false, //是否可枚举,就是可否遍历value:'zhengjiechun'})//设置多个属性的Object.defineProperties(person,{title:{configuration:false,writable:false,enumerable:true, //是否可枚举,就是可否遍历value:'测试多属性的defineProperties'},salary:{configuration:false,writable:true,enumerable:true, //是否可枚举,就是可否遍历value:'13000'},luck:{get:function(){return Math.random()>0.5?'good':'bad'}},promoto:{set:function(level){this.salary*=1+level*0.1}}})console.log('测试枚举=>',Object.keys(person)) //获取对象上的属性console.log('查看name有哪些属性标签=>',Object.getOwnPropertyDescriptor(person,'title'))console.log('原来的salary=>',person.salary) //13000person.promoto = 2console.log('后面的salary=>',person.salary) //15600
对象标签/对象序列化
[[proto]]、[[class]]、[[extensible]]
原型、类、是否可扩展
isFrozen是否被冻结
序列化、其他对象的方法
stringify()
解析序列化后的,转成json:JSON.parse()
序列化-自定义
/对象标签console.log('=========对象标签=========')console.log('=========序列化-自定义=========')var objj = {x:1,y:2,o:{o1:1,o2:2,toJSON:function(){return this.o1 + this.o2}}}console.log('序列化-自定义-toJSON方法是固定的=>',JSON.stringify(objj))//{"x":1,"y":2,"o":3}
其它对象方法-可自定义
console.log('=========其他对象方法=========')var objjj = {a:1,b:2}console.log('其他对象方法=>',objjj.toString())objjj.toString = function(){return this.a+this.b}console.log('其他对象方法=>',objjj.toString()) //3objjj.otherMethod = function(){return this.a+this.b+100}//自定义方法console.log('其他对象方法=>',objjj.otherMethod()) //103
五、数组
六、函数和作用域(函数、this)
- 函数概念
函数名、参数列表、函数体、一次定义,多次执行和调用
this/argument/作用域/不用调用方式/不同创建方法
不同调用方式
- 函数声明及表达式(创建函数的两种函数)
区别:函数声明会被前置,函数表达式只提前var add
命名函数表达式(不怎么用)是可以匿名的
var fn = function(){
}
var fn = function fnn(){
}
Function构造器(不怎么用)是匿名的
- this
全局this,就是window
console.log('===========this的使用==========')this.a = 36console.log(window.a) //36console.log(this === window) //trueconsole.log(this.document===document) //true
七、函数和作用域(闭包、作用域)
- 闭包的例子
//闭包的例子function outer(){var localvalue = 30return function(){return localvalue}}var func = outer()console.log(func())function outer(){var localvalue = 30return localvalue}//var func = outer() //报错,func不是一个函数//console.log(func())!function(){var localDate = "localData here"document.addEventListener('click',function(){console.log(localDate)})}()//输出localData here,前面加了!是变成函数表达式,后面才可以加()直接执行
- 闭包-循环常见错误
// for(var i=1;i<4;i++){
// document.getElementById('div'+i).addEventListener('click',function(){
// alert(i) //都是4,每一次点击的时候i都已经初始化完成后
// })
// }for(var i=1;i<4;i++){!function(i){document.getElementById('div'+i).addEventListener('click',function(){alert(i) //运用1,2,3})}(i)}
- 闭包-封装
(function(){var id = 1223;var name = 'zjc';var exports = {};var like = 'sss'exports.age = 12function converter(id){return +id;}exports.getId = function(){return converter(id);}exports.getName = function(){return name;}exports.getLike = function(){return like;}exports.setLike = function(_like){like = _likereturn like}window.exports = exports; //暴露给window}());console.log(exports.getId()) //1223console.log(exports.getName()) //zjcexports.age = 13console.log(exports.age) //13console.log(exports.getLike()) //sssexports.setLike('skskkld')console.log(exports.getLike()) //skskkld
总之:
优点:灵活、方便、封装
缺点:空间浪费、内存泄露、性能消耗
- 作用域
全局作用域、函数、eval
js没有块级作用域
函数有自己的独立作用域,比如函数内部变量
作用域链:从内向外
- es3执行上下文
八、OOP上
面向对象编程
- 概念与继承
继承、封装、多态、抽象
1、基于原型的继承
//一个函数对象的结构:属性function Foo(){}Foo.prototype.x = 1var obj = new Foo()//结构如下,prototype指Foo的对象属性,指向Object,//用于new出来的对象obj的原型,prototype和原型是两回事
// Foo.prototype
// {
// constructor:Foo,
// _proto_:Object.prototype,//原型,方法有toSring()、valueOf等
// x:1
// }
prototype是new出来的实例obj1、obj2、obj3的原型,如果要实例共享的方法,可以写在原型对象上添加共用的属性和方法
function Person(name,age){this.name = namethis.age = age}Person.prototype.hi = function(){console.log('Hi,的的名字是'+this.name + ',我的年龄是'+this.age)}Person.prototype.legs = 2Person.prototype.arms = 2Person.prototype.walk = function(){console.log(this.name + "正在走路")}function Student(name,age,className){Person.call(this,name,age)//调父类this.className = className}//让student实例继承person.prototype上的一些方法,Student和Person执行同一个原型,也可以各自添加自己的方法和属性,//不用Student.prototype = Person.prototypeStudent.prototype = Object.create(Person.prototype)//创建一个原型为Person.prototype的空对象,对象的原型指向一个参数Student.prototype.constructor = StudentStudent.prototype.hi = function(){console.log('Hi,我的名字是'+this.name + ',我的年龄是'+this.age+',来自'+this.className)}Student.prototype.learn = function(subject){console.log(this.name + '正在'+this.className+'学习' + subject)}var zjc = new Student('郑洁纯',25,'计科二班')zjc.hi()//Hi,我的名字是郑洁纯,我的年龄是25,来自计科二班console.log(zjc.legs)//2zjc.walk()//郑洁纯正在走路zjc.learn('数学')//郑洁纯正在计科二班学习数学
再谈原型链
- prototype属性
1、改变prototype
2、内置函数构造器的prototype
3、创建对象-new/原型链
- instanceof
- 实现继承的方式
九、OOP下
- 模拟重载
function Person(){var args = arguments//null的类型也是object要排除if(typeof args[0] === 'object'&&args[0]){//参数为对象的情况if(args[0].name){this.name = args[0].name}if(args[0].age){this.age = args[0].age}}else{if(args[0]){this.name = args[0]}if(args[1]){this.age = args[1]}}}Person.prototype.toString = function(){return 'name='+this.name +',age='+this.age}var zjc = new Person('zjc',25)console.log(zjc.toString())//OOP模拟重载、链式调用、模块化.html:35 name=zjc,age=25var nunn = new Person({name:'nunn',age:23})console.log(nunn.toString())//name=nunn,age=23
根据参数类型或者数量的区别去让同样的函数名字可以根据不同参数列表的情况去调用
- 调用子类的方法
1、call()和apply()
call, apply都属于Function.prototype的一个方法,它是JavaScript引擎内在实现的,因为属于Function.prototype,所以每个Function对象实例,也就是每个方法都有call, apply属性.既然作为方法的属性,那它们的使用就当然是针对方法的了.这两个方法是容易混淆的,因为它们的作用一样,只是使用方式不同.
相同点:两个方法产生的作用是完全一样的
不同点:方法传递的参数不同
当参数明确时可用call, 当参数不明确时可用apply给合arguments
2、基类和子类
//调用子类方法,apply和callfunction per(name){this.name = name}function stu(name,className){this.className = classNameper.call(this,name)//子类调用基类}var bosn = new stu('bosn','math')console.log(bosn)
3、链式调用
//链式调用function classManager(){}classManager.prototype.addClass = function(str){console.log('class:'+str+' added')return this}var manager = new classManager()manager.addClass('classA').addClass('classB').addClass('classC')//class:classA added//class:classB added//class:classC added
4、抽象类
5、es5的defineProperty()
seal取消对property的扩展
create
6、模块化
//模块化var moduleAmoduleA = function(){var prop = 1//内部的方法或变量不会泄露到外层,外层就放最核心的东西放全局作用域就行function func(){}return{func:func,prop:prop}}()console.log(moduleA)var moduleBmoduleB = new function(){var prop = 1function func(){}this.func=functhis.prop=prop}console.log(moduleB)
十、正则与模式的匹配
Javascript深入浅出相关推荐
- JavaScript深入浅出第2课:函数是一等公民是什么意思呢?
摘要: 听起来很炫酷的一等公民是啥? <JavaScript深入浅出>系列: JavaScript深入浅出第1课:箭头函数中的this究竟是什么鬼? JavaScript深入浅出第2课:函 ...
- JavaScript深入浅出第5课:Chrome是如何成功的?
摘要: Chrome改变世界. <JavaScript深入浅出>系列: JavaScript深入浅出第1课:箭头函数中的this究竟是什么鬼? JavaScript深入浅出第2课:函数是一 ...
- javascript深入浅出——学习笔记(六种数据类型和隐式转换)
在慕课之前学过JS深入浅出,最近发现很多东西都记不太清楚了,再复习一遍好了,感觉这个课程真的超级棒的,做做笔记,再添加一些学习内容?随时补充 课程大纲 1.数据类型 2.表达式和运算符 3.语句 4. ...
- Javascript深入浅出之this
在JavaScript中this为开发者提供了函数调用非常简洁的表达方式,但是关于Javascript中的this指向问题,我们经常听到的回答就是谁调用就指向谁. 实际的面试中的面试题中可以试试看能领 ...
- 8、JavaScript深入浅出——数据类型
一.六种数据类型 Javascript是弱类型. 五种原始类型和一种对象类型: number String boolean null undefined Object 二.隐式转换 +与-的运算举例: ...
- JavaScript深入浅出第1课:箭头函数中的this究竟是什么鬼?
摘要: 箭头函数极大地简化了this的取值规则. 普通函数与箭头函数 普通函数指的是用function定义的函数: var hello = function () {console.log(" ...
- Javascript深入浅出之闭包
在面试过程中,各位童鞋经常会被问道这样的问题:"请描述下你对闭包的理解",或者在面试烤卷中会有关于闭包的选择.填空题.如果是前者,大可一句带过:"闭包就是一个函数有权访问 ...
- Javascript深入浅出理解----汤姆大叔博客(二)
编写高质量JavaScript代码的基本要素 1)书写可维护代码 2)最小全局变量 JavaScript通过函数管理作用域.在函数内部声明的变量只在这个函数内部,函数外面不可用.另一方面,全局变量就是 ...
- 慕课网 javascript深入浅出编程练习
任务 请在index.html文件中,编写arraysSimilar函数,实现判断传入的两个数组是否相似.具体需求: 1. 数组中的成员类型相同,顺序可以不同.例如[1, true] 与 [false ...
最新文章
- Idea-每次修改JS文件都需要重启Idea才能生效解决方法
- linux ubuntu 开机自动启动 fixfox 并打开指定网站
- Anaconda 查找安装的环境,以及移除旧环境命令
- 及cp含义_新媒体运营炒CP,既好用,又好玩(第327回)
- Daily scrum 11.22
- python免费全套教程-python入门免费教程看这些就够了
- Linux 命令执行流程
- docker学习(1) 安装
- Treo 650使用专题及开发计划等
- 帆软报表更新到服务器控件展示不出来_如何报表控件FineReport实现自定义附件处理...
- 连云港师范专科学校计算机老师,喜报:我校学生在2021年中国大学生计算机设计比赛江苏省赛中获一等奖...
- 常见互联网域名及含义
- 杂谈eMule协议的由来
- 记忆力也靠后天培养!22个方法激发最强大脑
- 从PMP角度谈项目管理流程
- oracle 00600 kccpb,ORA-00600: [kccpb_sanity_check_2]报错处理一则
- 立方根用计算机怎么输入,平方根立方根怎么用电脑计算机表示?
- 【控制系统数字仿真与CAD——实验报告】实验三:离散相似法数字仿真(文末附完整代码 + 实验结果)
- 关于生命和人工智能的一些遐想
- github在线编辑
热门文章
- 一个API调用27个NLP预训练模型:BERT、GPT-2全囊括,像导入NumPy一样容易
- 对话Nullmax无人车CEO徐雷:造血营收L3,追梦宏图L4
- Android 6.0 变更
- spring注解@Component、@Repository、@Service、@Controller
- 8Manage CRM:智能时代会员“赢”销之宝
- 开源大数据周刊-第76期
- 课后作业:字符串加密
- iOS:MBProgressHUD的基本使用
- 未来数据中心的选择:宽带多模光纤(WBMMF)
- JavaScript正则表达式笔记