<!--
Created by wangyang on 2019-05-16.
itwangyang@gmail.com
http://www.itwangyang.xyz
-->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=Edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<meta name="format-detection" content="telephone=no">
<title>Title</title>
<meta name="description" content="">
<meta name="keywords" content="">
<!--所有的IE都起作用:-->
<!--[if IE]>
<link rel="stylesheet" type="text/css" href="all-ie-only.css/> <![endif]-->
</head>
<body>
<script>
/**
* 数据类型,----值类型:数字、字符串、布尔值、null、undefined
* 复杂数据类型:引用类型,对象:数组、函数、正则表达式、Date
*/
//变量没有声明过,--》如果获取变量的值,是会产生语法错误的 console.log(a);
/**
* undefined场景:
* 1.一个变量声明了,但是没有赋值 var a; console.log(a);
* 2.一个变量声明了,并且赋值了一个undefined的值,var b = undefined; console.log(b);
* 3.一个对象中,获取某个不存在的属性的值 var c ={};console.log(c.name);
*/
/**
* 面向对象:
* 对象是键值对的集合:对象是由属性和方法构成的;
*/
/**
* 对象属性的操作:
* 1. 第一种方式:.语法
* student.name
* 缺陷:后面不能使用js中的关键字、保留字(class/this/function/)
* 后面不能使用数字的
*
*
* 2. 第二种:使用更广,推荐
* student["name"]; 等价于 student.name
*
*设置属性:
* student ["gender"] = "男";
*
*
* 删除属性:
* delete student["gender"]
*
*/
//1.创建对象
const Person = {
gender: '男',
height: 185,
toShanghai: function () {
console.log('做?去上海');
}
};
//2.获取属性
console.log(Person.gender);
console.log(Person['height']);
//3.设置属性
Person.address = "上海市闸北区";
Person.height = 180;
//4.删除属性
delete Person.gender;
delete Person.a;
//5.清空对象
Person = {}; //Person对象不再具有任何属性
Person = null; //表示将Person变量的值赋为null,从此以后person不再是一个对象了
</script>
</body>
</html>
1.构造函数
<!--
Created by wangyang on 2019-05-16.
itwangyang@gmail.com
http://www.itwangyang.xyz
-->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=Edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<meta name="format-detection" content="telephone=no">
<title>Title</title>
<meta name="description" content="">
<meta name="keywords" content="">
<!--所有的IE都起作用:-->
<!--[if IE]>
<link rel="stylesheet" type="text/css" href="all-ie-only.css/> <![endif]-->
</head>
<body>
<script>
function Person(age, gender) {
this.age = age;
this.gender = gender;
//此时的内存依然浪费了---》原型
this.syaHello = function () {
}
}
//Person是p1的构造函数
let p1 = new Person(5, '女');
let p2 = new Person(51, '女');
let p3 = new Person(52, '女');
let p4 = new Person(15, '女');
let p5 = new Person(25, '女');
console.log(p1, p2, p3, p4, p5);
</script>
</body>
</html>
2.构造函数的返回值
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
</body>
<script>
//1、
function _fn(){
return 5;
}
var s=new _fn();
//s是_fn构造函数的实例
//2、
function _fn3(){}
var q1=new _fn3();
//q1是_fn3构造函数的实例
//3、
function fn3(){
return [1,3,5];
}
var qw=new fn3();//qw=[1,3,5]
console.log(qw);
//qw不是fn3构造函数的实例
//如何判断一个数据是否是复杂数据类型?
//使用排除法:
//a、看它的值是不是:数字、字符串、布尔值、null、undefined,
//b、如果不是以上5种值,那就是复杂数据类型
// 举例:
// [1,3,5]
// /abc/
// function(){}
// new Object();
//为什么要理解构造函数的返回值?
//String是一个内置函数
//a、String()
//b、new String()
//结论:一个函数通过new调用,或者不通过new调用,很多时候会有截然不同的返回值
//我如何分辨出一个对象到底是不是某个构造函数的实例?
//a、var isTrue=xxx instanceof Person
function Person(){
}
var p1=new Person();
console.log(p1 instanceof Person);//true,就是Person的实例
function Student(){
return 100;
}
var s1=new Student();
console.log(s1 instanceof Student);//true,就是Student的实例
function Programmer(){
return [1,3,5]
}
var pro=new Programmer();//pro并不是Programmer的实例
console.log(pro instanceof Programmer);//false
console.log("是数组的实例吗?",pro instanceof Array);//true
//小技巧:如何通过肉眼识别xxx对象时哪个构造函数的实例?
//xxx.__proto__属性,也是对象,该对象中一般都会有一个constructor属性,这个只想PPP函数,那么就可以认为:xxx是PPP构造函数的实例
//typeof运算符,只能判断:数字、字符串、布尔值、undefined、函数
//切记:千万不能使用typeof运算符来判断对象的构造函数
//typeof null === "object"
//typeof {} === "object"
//typeof [] === "object"
//typeof function(){} === "function"
//typeof /abc/ === "object"
</script>
</html>
3.为什么要继承?
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
</body>
<script>
function Person(name,age){
this.name=name;
this.age=age;
this.say=function(){}
}
var p1=new Person();
var p2=new Person();
//p1对象和p2对象的say方法是否是同一个方法:false
console.log(p1.say===p2.say);
//由于say方法可能功能相似,但是不是同一个方法(没有指向同一块内存,会造成内存浪费)
//解决方案:把say方法写在他们共同的(父对象)中
//其实他们共同的父对象,就可以通过:Person.prototype来获取
//-->只要把say方法写在Person.prototype中,那么say方法就是同一个方法
Person.prototype.run=function(){
console.log('时速500KM');
}
//此时p1和p2都可以访问到run方法
p1.run();
p2.run();
//验证p1.run和p2.run是否是同一个方法?
console.log(p1.run == p2.run); //指向同一个方法,这种方法避免了内存的浪费
console.log(p1.run == Person.prototype.run);
//true
var p3=new Person();
console.log(p3.run == p1.run); //true
console.log(p3.run === p1.run);//true
//结论:只要往某个构造函数的prototype对象中添加某个属性、方法,那么这样的属性、方法都可以被所有的构造函数的实例所共享
//==>这里的【构造函数的prototype对象】称之为原型对象
// Person.prototype是 p1 p2 p3 的原型对象
// Person.prototype是Person构造函数的【实例】的原型对象
//猜猜看?
// Person的原型对象是谁呢?
// -->首先要知道Person的构造函数:-->Function
// -->所以Person的原型对象是:Function.prototype
// p1的原型对象是谁呢?
// -->首先要知道p1是谁创建的? -->Person
// -->所以p1的原型对象时: Person.prototype
</script>
</html>
4.继承
<!--
Created by wangyang on 2019-05-17.
itwangyang@gmail.com
http://www.itwangyang.xyz
-->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=Edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<meta name="format-detection" content="telephone=no">
<title>Title</title>
<meta name="description" content="">
<meta name="keywords" content="">
<!--所有的IE都起作用:-->
<!--[if IE]> <link rel="stylesheet" type="text/css" href="all-ie-only.css/> <![endif]-->
</head>
<body>
<script>
function Person(name,age) {
this.name = name;
this.age = age;
this.sayHello = function () {
};
}
let p1 = new Person();
let p2 = new Person();
console.log(p1.sayHello === p2.sayHello);//false
//没有指向同一块内存,会造成内存浪费;解决方案:吧sayHello写在他们共同的(父对象)中
//其实他们共同的父对象,就可以通过Person.prototype来获取,就可以指向同一块内存中
Person.prototype.run = function () {
console.log('hha');
};
p1.run();
p2.run();
console.log(p1.run === p2.run);//true
//结论:只要往某个构造函数的prototype对象中添加某个属性,方法,那么这样的属性,方法都可以被所有的构造函数的实例所共享
//----》在这里,【构造函数的prototype对象】称为原型对象
/**
* Person的原型对象是谁?
* ---》手写要知道Person的构造函数:-----》Function
* --->所有Person的原型对象是:Function.prototype
*
*/
//继承第一种方式
function Tiger() {
}
Tiger.prototype = {
sayHello:function () {
},
eat:function () {
}
};
let tiger = new Tiger();
console.log(tiger.sayHello);
console.log(tiger.eat);
//缺点:添加1,2个无所谓,但是如果太多了,内存浪费
//继承的第一种方式:原型链继承1
/**
* Person.prototype.say=function(){
* console.log("你好")
* }
缺点:添加1、2个方法无所谓,但是如果方法很多会导致过多的代码冗余
// 继承的第二种方式:原型链继承2
Person.prototype={
constructor:Person,
say:function(){
console.log("你好");
},
run:function(){
console.log("正在进行百米冲刺");
}
}
注意点:
a、一般情况下,应该先改变原型对象,再创建对象
b、一般情况下,对于新原型,会添加一个constructor属性,从而不破坏原有的原型对象的结构
//继承的第三种方式:拷贝继承(混入继承)
场景:有时候想使用某个对象中的属性,但是又不能直接修改它,于是就可以创建一个该对象的拷贝
实现1: js var source={name:"李白",age:15} var target={}; target.name=source.name target.age=source.age;
上面的方式很明显无法重用,实际代码编写过程中,很多时候都会使用拷贝继承的方式,所以为了重用,可以编写一个函数把他们封装起来: js function extend(target,source){ for(key in source){ target[key]=source[key]; } return target; } extend(target,source)
由于拷贝继承在实际开发中使用场景非常多,所以很多库都对此有了实现
jquery:$.extend
es6中有了对象扩展运算符仿佛就是专门为了拷贝继承而生: js var source={name:"李白",age:15} var target={ ...source }
//继承的第四种方式:原型式继承
场景:
创建一个纯洁的对象
创建一个继承自某个父对象的子对象
使用方式:
- 空对象:Object.create(null)
var o1={ say:function(){} }
var o2=Object.create(o1);
继承的第五种方式:借用构造函数实现继承
场景:适用于2种构造函数之间逻辑有相似的情况
function Animal(name){ this.name=name; } function Person(name,age){ this.name=name; this.age=age; }
以上代码用借用构造函数实现 js function Animal(name,age){ this.name=name; this.age=age; } function Person(name,age,address){ Animal.call(this,name); //this.name=name; //this.age=age; this.address=address; }
*
*/
</script>
</body>
</html>