1.原型链
每一个实例对象有__proto__属性,指向的是构造函数的原型对象,构造函数的原型对象也是一个对象,也有__proto__属性,这样一层一层往上找就形成了原型链
<!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">
<title>Document</title>
</head>
<body>
<script>
// 在构造函数中,定义属性和方法 只要实例化一个对象,就会重新创建方法sing 就会开辟内存空间
// 浪费内存
// 我们要多个对象共用一个方法 把方法定义到原型对象中
function Star(name,age){
this.name = name;
this.age = age;
}
// 原型对象
Star.prototype.sing = function(){
console.log('唱歌把');
}
// 1.实例化对象 只要是对象就有__proto__ 指向原型对象
var s1 = new Star('张三',12);
s1.sing()
console.log(Star.prototype);
// new Object
// 2.我们Star原型对象的__proto__指向的是Object.prototype
console.log(Star.prototype.__proto__ === Object.prototype) //true
// 3.我们Object.prototype原型对象的__proto__指向null
console.log(Object.prototype.__proto__); //null
</script>
</body>
</html>
2.constructor构造函数
对象原型 proto 和构造函数prototype 原型对象里都有一个属性 constructor
constructor 我们称为构造函数,因为他指回构造函数本身
constructor 主要用来记录对象引用于那个构造函数
<!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">
<title>Document</title>
</head>
<body>
<script>
function Star(name,age){
this.name = name;
this.age = age;
}
// 我们修改了原来的原型对象 给原型对象赋值的是一个对象
// 我们手动的给constructor 指回原来的构造函数
Star.prototype = {
constructor:Star, //手动设置指向原来的构造函数
sing:function(){
console.log('唱歌')
},
movie:function(){
console.log('看电影')
}
}
var s = new Star('李四',23);
console.log(s);
</script>
</body>
</html>
3.原型对象中this的指向
构造函数中的this和原型对象中的this 都指向我们new出来的实例对象
<!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">
<title>Document</title>
</head>
<body>
<script>
function Star(name,age){
this.name = name;
this.age = age;
}
Star.prototype.sing = function(){
console.log('唱歌把')
}
Star.prototype.sex = '女';
var s = new Star('小写',34);
console.log(s.sex); //女
console.log(Object.prototype);
console.log(s);
console.log(Star.prototype);
console.log(s.toString());
/*
当访问一个对象的属性或方法时,首先先查找这个对象自身有没有该属性
如果没有就找它的原型(也就是__prot__指向的prototype原型对象)
如果还没有找到就查找原型对象的原型(Object的原型对象)
类推 一直找到Object为止 null
*/
</script>
</body>
</html>
<!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">
<title>Document</title>
</head>
<body>
<script>
/*
构造函数中的this和原型对象中的this都指向我们new出来的实例对象
*/
function Star(name,age){
this.name = name;
this.age = age;
}
var that;
Star.prototype.sing = function(){
console.log('我会唱歌');
that = this;
}
var s = new Star('小妞' ,23);
s.sing();
console.log(that === s); //true
</script>
</body>
</html>
4.继承
call
call() 可以调用函数
call()可以修改this的指向,使用call()的时候,参数1是修改后的this指向,参数2,参数3 使用逗号隔开
构造函数继承
<!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">
<title>Document</title>
</head>
<body>
<script>
// function fn(x,y){
// console.log('我想吃');
// console.log(this);
// console.log(x + y);
// }
// var o = {
// name:'zx'
// }
// fn(12,34);
/*
call()可以调用函数
call()可以修改this指向,使用call()的时候,参数1是修改后的this指向,参数2,参数3 使用逗号隔开
*/
// fn.call(o,23,56);
// 构造函数继承
// 只能继承父类的实例属性和方法 不能继承原型属性或者方法
// 父构造函数
function Parentl(){
this.name = 'parentl'
}
Parentl.prototype.getName = function(){
return this.name
}
// 子构造函数
function Child(){
// this指向子构造函数的对象实例
Parentl.call(this); //c
this.type = 'child';
}
var c = new Child();
console.log(c);
console.log(c.getName()) //报错
// 父类原型对象中一旦存在父类之前自己定义的方法,那么子类将无法继承这些方法
</script>
</body>
</html>
借用原型对象继承方法
<!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">
<title>Document</title>
</head>
<body>
<script>
// 1.父构造函数
function Parentl(name,age){
// this指向父构造函数的实例
this.name = name;
this.age = age;
}
Parentl.prototype.money = function(){
console.log(1000000);
}
// 子构造函数
function Child(name,age,score){
// this指向子构造函数的对象实例
Parentl.call(this,name,age); //c
this.score = score;
}
Child.prototype = new Parentl();
// 利用对象的形式修改了原型对象,手动设置constructor
Child.prototype.constructor = Child
Child.prototype.ks = function(){
console.log('考试')
}
var c = new Child('zs',20,98);
console.log(c);
console.log(c.money)
console.log()
</script>
</body>
</html>
5.数组新增方法
通过原型为数组扩展内置方法
<!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">
<title>Document</title>
</head>
<body>
<script>
/*
数组.push
数组.splice
数组.shift
---------
都是定义在
Array.prototype原型对象上
*/
// var arr = new Array()
// console.log(arr)
// 为数组扩展内置的方法
Array.prototype.sum = function(){
// this 指向的是arr
var sum = 0;
for(var i =0; i < this.length; i++){
sum += this[i]
}
return sum
}
var arr = new Array()
arr.push(23,45,1,2,4,5,7)
console.log(arr)
console.log(arr.sum());
</script>
</body>
</html>
forEach遍历数组
<!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">
<title>Document</title>
</head>
<body>
<script>
var arr = [12,4,5,6,78,5,4,32,46,8,9];
// arr.forEach(function(value,index,array){
// // value数组每一个元素
// // index数组元素的索引
// // array 当前的数组
// console.log(value,index,array);
// })
// // forEach 数组遍历 相当于for循环
// arr.forEach((item,index,arr)=>{
// console.log(item,index,arr)
// })
// ----------------------------
// filter过滤数组 返回过滤后的新数组
var newarr = arr.filter(function(value,index,array){
return value >=10
})
console.log(newarr) //[12, 78, 32, 46]
// some every findIndex map
</script>
</body>
</html>