## 1.继承的实现方式
### 1. 混入式继承(for in)
<script>
<script>
//当前没有的属性和方法,别人有,拿过来用 ,就是继承
var o = {
}
var obj = {
name :"张三",
age : 18,
sayHello :function () {
console.log("Hello world");
}
}
//混入式继承
for(var k in obj){
o[k] = obj[k];
}
console.log(o);
</script>
### 2.经典继承
<script>
//《JavaScript语言精粹》作者提出了一个方式来实现继承
// function jicheng(obj){
// var o = {};
// o.__proto__ = obj;
// return o;
// }
//
// var o = jicheng({name:"张三"});
// console.log(o);
//经典继承的语法
//Object.create(obj)
//返回值为一个对象,继承自参数中的obj
//这个方法是ES5中出来的,所以存在兼容性问题
// var o = {
// name:"周三"
// };
// var obj = Object.create(o);
//
// console.log(obj.name);
//如何处理Object.create的兼容性问题
var obj = {
name:"周三"
};
//检测浏览器的能力,如果没有Object.create方法就给他添加一个(不推荐使用)
if(Object.create){
var o = Object.create(obj);
}else{
Object.create = function () {
function F() {
}
F.prototype = obj;
var o = new F();
}
var o = Object.create(obj);
}
//自己定义个函数
function create(obj){
if(Object.create){
return Object.create(obj);
}else{
function F() {
}
F.prototype = obj;
return new F();
}
}
</script>
### 3.原型继承
<script>
//原型继承
//利用原型中的成员可以被和其相关的对象共享这一特性,可以实现继承
//这种实现继承的方式,就叫做原型继承
//1.给原型对象中添加成员(通过对象的动态特性) 不是严格意义上的继承
function Person(name, age){
this.name = name;
this.age = age;
}
Person.prototype.sayHello = function () {
console.log("我想死你了");
}
var p = new Person("冯巩",50);
p.sayHello();
//这里的p对象就继承原型
//2.直接替换原型对象
function Person(name, age){
this.name = name;
this.age = age;
}
Person.prototype.sayHi = function () {
console.log("Hey man");
}
var parent = {
sayHello : function () {
console.log("我想你死了");
}
}
Person.prototype = parent;
var p = new Person("冯巩",50);
p.sayHello();
p.sayHi(); 替换之后,sayHi方法不复存在
//p对象继承了原型对象(parent对象)
//注意:使用替换原型的方式实现继承的时候,原有原型中的成员就会丢失
//3.利用混入的方式给原型对象添加成员
function Person(name, age){
this.name = name;
this.age = age;
}
Person.prototype.sayHi = function () {
console.log("Hey man");
}
var parent = {
sayHello : function () {
console.log("我想你死了");
}
}
for(var k in parent){
Person.prototype[k] = parent[k];
}
var p = new Person("冯巩",50);
p.sayHello();
//也是实现了继承 p继承自原型对象
</script>
### 4.继承的应用
<script>
var arr = [1, 2, 3];
//开发人员A想要的sayHello
Array.prototype.sayHello =function () {
console.log("来呀,互相伤害啊");
}
//开发人员B想要的sayHello
Array.prototype.sayHello =function () {
console.log("我是一个数组,很高兴认识你,呵呵")
}
//如果直接修改内置对象的原型,会影响整个开发团队
arr.sayHello();
//扩展内置对象(就是给内置对象新增成员)
//var str = "+++abc+++";
//console.log(str.trim("+"));
//作业:扩展String内置对象,强化trim功能
//如何安全的扩展一个内置对象
function MyArray() {
//我自己的属性
this.name = "我是一个数组";
this.sayHello = function () {
console.log("我的sayHello方法");
}
}
var arr = new Array();
//继承之后,我的数组中就有了原生数组对象的所有的属性和方法
MyArray.prototype = arr;
MyArray.prototype.safdaf =function () {
}
//myArr这个对象就继承自arr
var myArr = new MyArray();
myArr.push(100);
myArr.push(2,3,4,5)
console.log(myArr);
var arr = new Array();
function BdeArray(){
this.sayhello=function () {
}
}
BdeArray.prototype = [];
var arr = new BdeArray();
var arr = new MyArray();
</script>
## 2.原型链
### 1.原型链结构概述
<script>
//1.什么是原型链?
//每个构造函数都有原型对象
//每个对象都会有构造函数
//每个构造函数的原型都是一个对象
//那么这个原型对象也会有构造函数
//那么这个原型对象的构造函数也会有原型对象
//这样就会形成一个链式的结构,称为原型链
//2.原型链结构的基本形式
function Person(name){
this.name = name;
}
var p = new Person();
//p ---> Person.prototype --->Object.prototype---->null
//属性搜索原则:
//1.当访问一个对象的成员的时候,会现在自身找有没有,如果找到直接使用,
//2.如果没有找到,则去当前对象的原型对象中去查找,如果找到了直接使用,
//3.如果没有找到,继续找原型对象的原型对象,如果找到了,直接使用
//4.如果没有找到,则继续向上查找,直到Object.prototype,如果还是没有,就报错
//原型继承概念
//通过修改原型链结构实现的继承,就叫做原型继承
</script>
## 3.Object.prototype的成员
<script>
//1.constructor
//原型对象内的一个属性,指向该原型对象相关联的构造函数
//2.hasOwnProperty
//一个方法,用来判断对象本身(不包含原型)是否拥有某个属性
function Person(){
this.name = "王九"
}
Person.prototype.name = "张三";
var p = new Person();
console.log(p.name);
console.log(p.hasOwnProperty("__proto__"));
//3.propertyIsEnumerable
// 1. 判断属性是否属于对象本身
// 2. 判断属性是否可以被遍历
console.log(p.propertyIsEnumerable("name"));
//Object.defineProperty();
// 使用以上方法添加属性的时候,可以附加一些信息,
// 例如这个属性是否可写 可读 可遍历
for(var k in p){
console.log(k);
}
//4. toString 和 toLocaleString
var o = {};
console.log(o.toString());
console.log(o.toLocaleString());
var now = new Date();
console.log(now.toString());
console.log(now.toLocaleString());
//5.valueOf
//获取当前对象的值
function Person(){
}
var p = new Person();
//在对象参与运算的时候
//1.默认的会先去调用对象的valueOf方法,
//2.如果valueOf获取到的值,无法进行运算 ,就去去调用p的toString方法 最终做的就是字符串拼接的工作
console.log( 1 + p);
//6. __proto__
//原型对象对象中的属性
//可以使用 对象.__proto__ 去访问原型对象
</script>
- constructor :指向和该原型相关的构造函数
- hasOwnProperty 方法: 判断对象本身是否拥有某个属性
- properIsEnumerable 方法: 1.判断属性是否属于对象本身,2.判断属性是否可以被遍历
- toString toLocaleString: 将对象转换成字符串 toLocalString转换成字符串的时候应用的本地的设置格式
- valueOf 方法:在对象参与运算的时候,首先调用valueOf方法获取对象的值,如果该值无法参与运算,将会调用toString方法
- __proto__ 属性: 指向当前对象的原型对象
## 4.创建函数的几种方式
<script>
//1.直接声明函数
function funcName(/*参数列表*/){
//函数体
}
//2.函数表达式
var funcName = function(){
};
//3.new Function
var func = new Function();
</script>
### 1.Function的使用
<script>
function Person(name, age){
this.name = name;
this.age = age;
}
var p = new Person("张三",19);
// var func = new Function("console.log('我是动态创建的函数');console.log(1);");
// func();
//Function这构造函数 可以用来新建函数对象
//语法:
//0.一个参数都不传的情况 创建的就是一个空的函数
//var 函数名 = new Function()
//1.只传一个参数的情况 这个参数就是函数体
//var 函数名 = new Function("函数体")
//2.传多个参数的情况,最后一个参数为函数体,前面的参数都是该函数的形参名
//练习:使用Function创建一个打印4句歌词的函数
// var func = new Function("console.log('4句歌词');");
// func();
//举个栗子
//创建一个计算两个数的和的函数
// var sum = new Function("a", "b", "return a + b;");
// console.log(sum(1, 1111));
// 练习: 利用 Function 创建一个求三个数中最大数的函数.
// var max = new Function("a", "b", "c", "return (a > b ? a : b)> c ? (a > b? a : b):c;");
// console.log(max(34, 45, 11));
//练习:传入一个数组,求这个数组中的最大数
// var max = new Function("arr",
// "var maxNum = arr[0];" +
// "for(var i = 1;i<arr.length;i++){" +
// "if(maxNum < arr[i]){" +
// "maxNum = arr[i];" +
// "}" +
// "}" +
// "return maxNum;"
// )
//
// console.log(max([1, 2, 3, 44, 5, 6]));
window.onload =function () {
var script = document.getElementById("funcContent");
var str = script.innerHTML;
var max = new Function("arr", str);
console.log(max([1, 2, 3, 44, 5, 6]));
}
//如何解决使用Funciton创建函数时,代码过长的问题
//1.可以使用字符串拼接 让代码换行
//2.使用模板的方式,将代码写在模板标签内(模板引擎),获取该标签的内容
//3.使用反引号(`) 引住字符串,那么就可以 换行了
var str = `adfafdsa
asdfas`;
console.log(str);
// 利用 Function 创建一个函数,
// 要求允许函数调用时传入任意个数参数,
// 并且函数返回这些数字中最大的数字.
// function test(){
//
// }
//
// test(1,234,4);
</script>
<script type="text/template" id="funcContent">
var maxNum = arr[0];
for(var i = 1; i<arr.length; i++){
if(maxNum < arr[i]){
maxNum = arr[i];
}
}
return maxNum;
</script>
#### 1.1 模板引擎的代码块书写例子
<script type="text/template" id="funcContent">
var maxNum = arr[0];
for(var i = 1; i<arr.length; i++){
if(maxNum < arr[i]){
maxNum = arr[i];
}
}
return maxNum;
</script>
### 2.argument对象
<script>
// 要求允许函数调用时传入任意个数参数,
// 并且函数返回这些数字中最大的数字.
//函数内部的一个对象 arguments
//当函数调用的时候,系统会将所有传入的实参,依次存入这个数组对象
function max(){
// console.log(arguments);
var maxNum = arguments[0];
for (var i = 1; i < arguments.length; i++) {
maxNum = maxNum > arguments[i] ? maxNum :arguments[i];
}
return maxNum;
}
console.log(max(1, 2, 34, 5, 6));
//练习,使用Function创建一个函数,
//给函数传入任意个数的参数,
//在函数内进行去重操作,然后返回去重后的数组
var distinct = new Function(`
var arr = [];
for (var i = 0; i < arguments.length; i++) {
if(arr.indexOf(arguments[i])==-1){
arr.push(arguments[i]);
}
}
return arr;
`);
// console.log(distinct(1, 2, 34, 34, 5, 5));
function test(a, b){
console.log(a , b);
console.log(arguments);
}
test();
//1.一个函数有形参的时候,调用的时候,可以不传参数
//2.一个函数没有形参的时候,调用时后,可以传参 arguments对象
//3.一个函数不管有没有形参,调用的时候都会把实参的值存入arguments对象
4.arguments
//函数内部的一个对象,在函数调用的时候,默认的会将所有传入的实参依次存入该对象
//是一个伪数组
//arguments.length 可以用来表示传入实参的个数
//arguments.callee 指向函数本身
</script>
### 3.eval函数
<script>
//eval函数可以用来将字符串转换成JavaScript代码并且运行
var str = "var a = 10";
eval(str);
console.log(a);
//JSON格式的数据 JSON对象有兼容性问题
var jsonData = '({"name":"zs", "age":18})';
var o = JSON.parse(jsonData);
console.log(o);
eval("var o = "+ jsonData);
var o = eval(jsonData);
console.log(o);
//使用eval来解析JSON格式字符串的时候,会将{}解析为代码块,而不是对象的字面量
//1.在JSON格式的字符串前面拼接上 "var o ="
//2.把JSON格式的字符串使用()括起来,就不会将{}解析为代码块,而是表达式
var str = prompt("请输入内容");
eval(str);
//不推荐使用eval
</script>
</head>
### 4.eval和Function的区别
1.Function和eval有什么区别
//共同点,都可以将字符串转换成js代码
//不通点:
//1.Function 创建出来的是 函数 并不会直接调用,只有当手动去调用创建出来的函数的时候,才
会执行
//2.eval 把字符串转成代码之后,直接就执行了
2.Function 和 eval
1.Function 可以用来创建函数 (Function可以看做是一个构造函数,用来实例化函数对象)
// 语法 var fun = new Function();
创建函数的时候 如果使用的是 new Function(); 创建一个空函数
创建函数的时候 如果使用的是 new Fucntion(参数); 只有一个参数,那么这个参数为要创建的函数的函数
创建函数的时候 如果使用的是 new Funciton(参数1,参数2,...参数n) 那么最后一个参数为函数的函数体面的所有参数为要创建的函数的形参名
//Function这个构造函数接收的所有的参数都是字符串类型的
2.eval 可以将字符串转换成js代码并且执行
当使用eval解析 JSON格式的数据(字符串)的时候
会将字符串内的{}当做代码块来解析,所以直接解析 会报错
解决方案:
1.在JSON格式的字符串前面拼接 "var 变量名 =" + JSON字符串
2.在JSON格式的字符串前后加上() "("+ JSON字符串 +")"
)
## 5.静态成员和实例成员
<script>
function Person(){
this.name = "zs";
this.run = function () {
console.log("跑");
}
}
Person.prototype
console.log(Person.name);
var p = new Person();
//p.name
//静态成员和实例成员的概念,是从其他编程语言中引入的
//静态成员:
//是指构造函数的属性和方法
//实例成员:
//是指实例的属性和方法
//__proto__
$("#id").css();
$("#id").text();
$.trim();
$.each();
$.extend();
//把工具方法,作为静态成员
//把跟对象相关的方法,作为实例成员
</script>