慕课网视频笔记: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 = 10

console.log('obj.z = >',obj.z)

Object.defineProperty(obj,'z',{

value:100,

configurable:true, //默认不可配置false,就不可以删除

writable:true //默认不可写false

})

console.log('obj.z = >',obj.z) //100

obj.z = 'slslsl'

console.log('obj.z = >',obj.z) //slslsl设置为可写了

delete obj.z

console.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) //13000

person.promoto = 2

console.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()) //3

objjj.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 = 36

    console.log(window.a) //36

    console.log(this === window) //true

    console.log(this.document===document) //true

七、函数和作用域(闭包、作用域)

闭包的例子

//闭包的例子

function outer(){

var localvalue = 30

return function(){

return localvalue

}

}

var func = outer()

console.log(func())

function outer(){

var localvalue = 30

return 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 = 12

function 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 = _like

return like

}

window.exports = exports; //暴露给window

}());

console.log(exports.getId()) //1223

console.log(exports.getName()) //zjc

exports.age = 13

console.log(exports.age) //13

console.log(exports.getLike()) //sss

exports.setLike('skskkld')

console.log(exports.getLike()) //skskkld

总之:

优点:灵活、方便、封装

缺点:空间浪费、内存泄露、性能消耗

作用域

全局作用域、函数、eval

js没有块级作用域

函数有自己的独立作用域,比如函数内部变量

作用域链:从内向外

es3执行上下文

八、OOP上

面向对象编程

概念与继承

继承、封装、多态、抽象

1、基于原型的继承

//一个函数对象的结构:属性

function Foo(){

}

Foo.prototype.x = 1

var 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 = name

this.age = age

}

Person.prototype.hi = function(){

console.log('Hi,的的名字是'+this.name + ',我的年龄是'+this.age)

}

Person.prototype.legs = 2

Person.prototype.arms = 2

Person.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.prototype

Student.prototype = Object.create(Person.prototype)//创建一个原型为Person.prototype的空对象,对象的原型指向一个参数

Student.prototype.constructor = Student

Student.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)//2

zjc.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=25

var 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和call

function per(name){

this.name = name

}

function stu(name,className){

this.className = className

per.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 moduleA

moduleA = function(){

var prop = 1

//内部的方法或变量不会泄露到外层,外层就放最核心的东西放全局作用域就行

function func(){

}

return{

func:func,

prop:prop

}

}()

console.log(moduleA)

var moduleB

moduleB = new function(){

var prop = 1

function func(){

}

this.func=func

this.prop=prop

}

console.log(moduleB)

十、正则与模式的匹配

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,732评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,496评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,264评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,807评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,806评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,675评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,029评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,683评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,704评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,666评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,773评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,413评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,016评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,978评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,204评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,083评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,503评论 2 343

推荐阅读更多精彩内容

  • 工厂模式类似于现实生活中的工厂可以产生大量相似的商品,去做同样的事情,实现同样的效果;这时候需要使用工厂模式。简单...
    舟渔行舟阅读 7,717评论 2 17
  • (一)函数 1.函数基本声明 function fun([参数1],[参数2],...){ 函数体; }; 2....
    妖妖灵嘛0阅读 283评论 0 0
  • 1、原型、原型链 1.1 原型的定义:原型是function对象的一个属性,原型定义了构造函数制造出的对...
    MrLsss阅读 249评论 0 1
  • 布尔操作符!false //true!"blue" //false!0 //true!NaN //true!...
    左钱钱阅读 390评论 0 0
  • 单例模式 适用场景:可能会在场景中使用到对象,但只有一个实例,加载时并不主动创建,需要时才创建 最常见的单例模式,...
    Obeing阅读 2,054评论 1 10