谷歌浏览器,会返回最后一行执行代码的返回值
什么是面向对象编程
面向过程是一种编程模型,由一系列要执行的计算步骤组成,通常采用自上而下,顺序执行的方式。
面向对象编程是一种计算机编程模型,它围绕数据或对象而不是功能或逻辑来组织软件,更专注于对象与对象之间的交互,对象涉及的方法和属性都在对象内部,说的更底层一点就是面向对象是一种依赖于类和对象概念的编程方式。
面向对象的三大特征
1.封装
封装就是将变量和方法包装在一个单元中,其唯一目的是从外部类中隐藏数据。这使得程序结构更容易管理,因为每个对象的实现和状态都隐藏在明确定义的边界之后。
2.继承
继承是指从多种实现类中抽象出一个基类,使得具备多种实现类的共同特性。比如猫类,狗类,虎类中可以抽象出一个动物类,具有猫,狗,虎的共同特性(吃,跑,叫等)
3.多态性
多态性是指具体多种形态或者实现方式,Java中的多态允许类的子类定义它们自己的唯一行为,并且还共享父类的一些共相同功能。
封装
ES6之前的封装是使用构造函数来实现的(构造函数过于抽象,就新出了个class)
ES6之后的封装使用class(写前端常用但是逆向少见,因为逆向的话尤其是使用框架去做的话,它大部分情况会把代码降到ES5去执行为了去兼容不同的浏览器,所以一般很少见到class)
提到构造函数,那么我们先来看一个概念,顺便回忆一下我们原型链的知识。
详解new
function Test(name) { this.name = name } Test.prototype.sayName = function () { console.log(this.name) } const t = new Test('anlan') console.log(t.name) t.sayName()
new的过程发生了什么?
1. 创建了一个全新的对象。 2. 这个对象会被执行[[Prototype]](也就是__proto__)链接。
3. 生成的新对象会绑定到函数调用的this。 4. 通过new创建的每个对象将最终被[[Prototype]]链接到这个函数的prototype对象上。 但是当下的构造函数 Test 并没有显式 return 任何值(默认返回 undefined),如果我们让它返回值会发生什么事情呢? function Test(name) { this.name = name return 1 } const t = new Test('anlan') console.log(t.name)
虽然上述例子中的构造函数中返回了 1,但是这个返回值并没有任何的用处,得到的结果还是和之前的例子完全一样。那么通过这个例子,我们又可以得出一个结论:构造函数如果返回原始值(虽然例子中只有返回了 1,但是你可以试试其他的原始值,结果还是一样的),那么这个返回值毫无意义 如果返回引用类型呢? function Test(name) { this.name = name console.log(this) return { age: 26 } } const t = new Test('anlan') console.log(t) console.log(t.name)
function Test(name) { this.name = name console.log(this) return []/fn/null } const t = new Test('anlan') console.log(t) console.log(t.name)
ES6的class实际就是一个语法糖,那么在ES6之前,是没有类这个概念的,因此是借助于原型对象和构造函数来实现。
1. 私有属性和方法:只能在构造函数内访问不能被外部所访问(在构造函数内使用var等声明的属性)
2. 公有属性和方法(或实例方法):对象外可以访问到对象内的属性和方法(在构造函数内使用this设置,或者设置在构造函数原型对象上比如Cat.prototype.xxx)
3. 静态属性和方法:定义在构造函数上的方法(比如Foo.xxx),不需要实例就可以调用(console.dir(Object))
例1: function Foo(arg1,arg2){var private1='pri1';var private2='pri2';var private3=function(){console.log(private1+private2)};this.pub1=arg1;this.pub2=arg2;this.pub3=function(){private3();console.log('finish')}}var foo=new Foo('arg1','arg2');console.log(foo);foo.pub3(); 在这段代码中: private1、 private2、 private3 是私有属性,在外部【指foo】是看不到也用不了的。 pub1、pub2、pub3 是公有属性 在函数内用var等定义的就是私有的 在函数内用this承接的就是公有
现在我们尝试理解一下静态属性方法和公有属性方法 function Foo(arg1,arg2){var private1='pri1';var private2='pri2';var private3=function(){console.log(private1+private2)};this.pub1=arg1;this.pub2=arg2;this.pub3=function(){private3();console.log('finish')}}Foo.descript='1这是一段讲述静态属性方法的代码1';Foo.descript2=function(){console.log('2这是一段讲述静态属性方法的代码2')};Foo.prototype.descript3=function(){console.log('1这是一段讲述公有属性方法的代码1')};var foo=new Foo('arg1','arg2');console.log(Foo.descript);Foo.descript2();console.log(foo.descript);foo.descript3(); 在构造函数上也就是使用Foo.xxx定义的是静态属性和方法 在构造函数内使用this设置,或者设置在构造函数原型对象上比如Foo.prototype.xxx,就是公有属性和方法(实例方法)
理解实例自身的属性和定义在构造函数原型对象中的属性的区别
function Foo(name){this.name=name}Foo.prototype.pro1='我是构造函数原型对象上的属性';Foo.prototype.pro2=function(){console.log('小不点')};var foo=new Foo('anlan');console.log(foo);console.log(foo.name);console.log(foo.pro1);foo.pro2(); 定义在构造函数原型对象上的属性和方法虽然不能直接表现在实例对象上,但是实例对象却可以访问或者调用它们
如何区分他们是在本身属性上面还是在原型上面?
采用 foo.hasOwnProperty(key),返回值 布尔类型
思考题
ES6之后的封装
在ES6之后,新增了class 这个关键字。它可以用来代替构造函数,达到创建“一类实例”的效果。并且类的数据类型就是函数,所以用法上和构造函数很像,直接用new命令来配合它创建一个实例。类的所有方法都定义在类的prototype属性上面。
假类
最简单的class
class Foo{ constructor(a){this.name=a} }
思考:class Foo{constructor(arg1,arg2){var p1='p1';var p2='p2';var p3=function(){console.log(p1+p2)};this.p4=arg1;this.p5=arg2;this.p6=function(){p3();console.log('卧槽')}}};var foo=new Foo('arg1','arg2');console.log(foo);foo.p6();
class Foo{constructor(){var p1='luck';this.p2='foo';this.p3=function(){}};p4='white';p5=function(){console.log('我追你如果我追到你')};p6(){console.log('我就把你嘿嘿嘿')}}var foo=new Foo();console.log(foo);foo.p5();foo.p6();
你还可以使用static标识符表示它是一个静态的属性或者方法 class Foo{static d1='安之若素';static d2(){console.log('波澜不惊')}static d3=function(){console.log('凛冬已至,冰冷刺骨')}}
关于class的变量提升
var a = new A();function A () {};console.log(a);var b = new B();class B {};console.log(b);
掺杂作用域
class Cat{constructor(){this.name='guaiguai';var type='constructor'}type='class';getType=function(){console.log(this.type);console.log(type)}}var type='window';var guaiguai=new Cat();guaiguai.getType();
掺杂箭头函数
class Cat{constructor(){this.name='guaiguai';var type='constructor'}type='class';getType=()=>{console.log(this.type);console.log(type)}}var type='window';var guaiguai=new Cat();guaiguai.getType();console.log(guaiguai);
class Cat{constructor(){this.name='cat1'}name='cat2';getName=function(){console.log(this.name)}}var cat=new Cat();cat.getName();
class Cat{constructor(){this.name='cat1'};name='cat2';getName=function(){console.log(this.name)}}Cat.prototype.name='cat3';var cat=new Cat();cat.getName();
class Cat{constructor(){this.name='guaiguai';var type='constructor';this.getType=()=>{console.log(this.type);console.log(type)}}type='class';getType=()=>{console.log(this.type);console.log(type)}}var type='window';var guaiguai=new Cat();guaiguai.getType();console.log(guaiguai);
加菜
虽然报错但是程序仍会运行。
显示一个由特定的 Javascript 对象列表组成的可交互列表。这个列表可以使用三角形隐藏和显示来审查子对象的内容。